From ef7d52e56ce938c5104bb5112fc244400d6c7754 Mon Sep 17 00:00:00 2001 From: Kyle King Date: Fri, 14 Jul 2017 23:55:19 -0400 Subject: [PATCH 1/2] init: `unsubscribe` as internal package Integrate n1-unsubscribe into nylas-mail directly See: https://github.com/colinking/n1-unsubscribe --- README.md | 2 +- .../internal_packages/unsubscribe/README.md | 16 ++ .../assets/toolbar-unsubscribe-error@1x.png | Bin 0 -> 498 bytes .../assets/toolbar-unsubscribe-error@2x.png | Bin 0 -> 1098 bytes .../assets/toolbar-unsubscribe-loading@1x.png | Bin 0 -> 569 bytes .../assets/toolbar-unsubscribe-loading@2x.png | Bin 0 -> 1100 bytes .../assets/toolbar-unsubscribe-success@1x.png | Bin 0 -> 502 bytes .../assets/toolbar-unsubscribe-success@2x.png | Bin 0 -> 1040 bytes .../assets/toolbar-unsubscribe@1x.png | Bin 0 -> 530 bytes .../assets/toolbar-unsubscribe@2x.png | Bin 0 -> 1114 bytes .../assets/unsubscribe-error@1x.png | Bin 0 -> 631 bytes .../assets/unsubscribe-error@2x.png | Bin 0 -> 1075 bytes .../assets/unsubscribe-loading@1x.png | Bin 0 -> 654 bytes .../assets/unsubscribe-loading@2x.png | Bin 0 -> 1223 bytes .../assets/unsubscribe-success@1x.png | Bin 0 -> 660 bytes .../assets/unsubscribe-success@2x.png | Bin 0 -> 1406 bytes .../unsubscribe/assets/unsubscribe@1x.png | Bin 0 -> 749 bytes .../unsubscribe/assets/unsubscribe@2x.png | Bin 0 -> 1587 bytes .../internal_packages/unsubscribe/icon.png | Bin 0 -> 7479 bytes .../unsubscribe/keymaps/unsubscribe.json | 3 + .../lib/enum/threadConditionType.es6 | 6 + .../unsubscribe/lib/main.jsx | 51 +++++ .../lib/thread-unsubscribe-store-manager.es6 | 17 ++ .../lib/thread-unsubscribe-store.es6 | 204 ++++++++++++++++++ .../lib/ui/unsubscribe-buttons.jsx | 162 ++++++++++++++ .../lib/ui/unsubscribe-preferences.jsx | 46 ++++ .../unsubscribe/lib/util/blacklist.es6 | 38 ++++ .../unsubscribe/lib/util/email-parser.es6 | 177 +++++++++++++++ .../unsubscribe/lib/util/helpers.es6 | 59 +++++ .../unsubscribe/package.json | 24 +++ .../internal_packages/unsubscribe/plugin.png | Bin 0 -> 27974 bytes .../unsubscribe/spec/util/blacklist-spec.es6 | 13 ++ .../spec/util/email-parser-spec.es6 | 62 ++++++ .../unsubscribe/spec/util/helpers-spec.es6 | 27 +++ .../unsubscribe/stylesheets/main.less | 52 +++++ packages/client-app/package.json | 4 + 36 files changed, 962 insertions(+), 1 deletion(-) create mode 100755 packages/client-app/internal_packages/unsubscribe/README.md create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-error@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-error@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-loading@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-loading@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-success@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-success@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-error@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-error@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-success@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-success@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@1x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@2x.png create mode 100755 packages/client-app/internal_packages/unsubscribe/icon.png create mode 100755 packages/client-app/internal_packages/unsubscribe/keymaps/unsubscribe.json create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/enum/threadConditionType.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/main.jsx create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store-manager.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-buttons.jsx create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-preferences.jsx create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/util/blacklist.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/util/email-parser.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/lib/util/helpers.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/package.json create mode 100755 packages/client-app/internal_packages/unsubscribe/plugin.png create mode 100755 packages/client-app/internal_packages/unsubscribe/spec/util/blacklist-spec.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/spec/util/email-parser-spec.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/spec/util/helpers-spec.es6 create mode 100755 packages/client-app/internal_packages/unsubscribe/stylesheets/main.less diff --git a/README.md b/README.md index ea33e2d25..8410feac7 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Great starting points for creating your own plugins! - [View on GitHub](https://github.com/nylas/nylas-mail/tree/master/internal_packages/message-view-on-github) - [Personal Level Indicators](https://github.com/nylas/nylas-mail/tree/master/internal_packages/personal-level-indicators) - [Phishing Detection](https://github.com/nylas/nylas-mail/tree/master/internal_packages/phishing-detection) +- [Unsubscribe](https://github.com/nylas/nylas-mail/tree/master/internal_packages/unsubscribe) #### Community Plugins @@ -96,7 +97,6 @@ Note these are not tested or officially supported by Nylas, but we still think t - [Jiffy](http://noahbuscher.github.io/N1-Jiffy/)—Insert animated GIFs - [Weather](https://github.com/jackiehluo/n1-weather) - [Todoist](https://github.com/alexfruehwirth/N1TodoistIntegration) -- [Unsubscribe](https://github.com/colinking/n1-unsubscribe) - [Squirt Speed Reader](https://github.com/HarleyKwyn/squirt-reader-N1-plugin/) - [Website Launcher](https://github.com/adriangrantdotorg/nylas-n1-background-webpage)—Opens a URL in separate window - In Development: [Cypher](https://github.com/mbilker/cypher) (PGP Encryption) diff --git a/packages/client-app/internal_packages/unsubscribe/README.md b/packages/client-app/internal_packages/unsubscribe/README.md new file mode 100755 index 000000000..dbd947dba --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/README.md @@ -0,0 +1,16 @@ +![Unsubscribe: unsubscribe without leaving N1](plugin.png) + +Quickly unsubscribe from emails without leaving N1. The unsubscribe plugin parses the `list-unsubscribe` header and the email body to look for the best way to unsubscribe. If an unsubscribe email address can be found, the plugin will send one in the background on your behalf. If only a browser link is found, either a mini N1 browser window will open or for certain cases, you will be redirected to your default browser. + +## Keyboard Shortcuts + +Press CMD + ALT + U when viewing an email. This shortcut can be changed in the preference panel (`Nylas->Preferences->Unsubscribe`). + +## Reporting Bugs + +- **Feature Requests or Bug Reports**: Submit them through the [issues](issues) pane. +- **Mishandled Emails**: Find an email which this plugin doesn't handle correctly? Not finding an unsubscribe link when there should be one? Forward the email to us at n1.unsubscribe@gmail.com and we'll look into it. + +## Made by + +[Kyle King](http://kyleking.me) and [Colin King](http://colinking.co) diff --git a/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-error@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-error@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..0812e36553b51a3679f9987bac628a3e8c1e792d GIT binary patch literal 498 zcmVPx$tVu*cR5%f}lFdp2Q546|xnq`nP$8uiMLj^2=s0O1QYq0wA@Bj}6@r%S0ynjf z9wAx;EmB&vkZdYH+O(==lmtbTfz!;r%@wXphFXgb4Ci;x`JXfAegOQpdA)(j`hWQS zp$QQq0vdUWIPLK&>mu*-1w5Kj*%51-fJUA$=YauFMYBmK0Zi+R9swb7p+^qUXtb;J z{I<$jLb%OeW{)`w3kHLOWzEO}1GglRmHb6EC34j*JeAA6z-SVI4N=DCWH~e{1l)gU z#uNbdnRrhrU9#q?6L@B4hiOI6U0EPi(MMxH!w^awo6-Jspb_aEuq%j88D-Qyyx8KS0X~TJ@@3BLWVXQ`}h#2!lOy zuSp*B`xl%VEl(D&&QHH-_#z&OJhn@0q(g$B_yBD&2Ds*t1DjlfXgEx_!P#onTd)SK ztSE}BqGQ@@bZ94Sd!J0(H78iMYMP#bs;Z@Khb;_1BO0r0SqlX>ZNNpDOy|Hd^ o=*JroO@8GQiG*F2!|rPx(1W80eR9Fe^S8r%rRTMw>y_YtX)~*w}wWSqNaKo`COJe@CN_5>u+sVGHD7Y~Y z>WA&4O#GnGv58pxR{SDUCgQh>Rvg7@MM|19OJ0)}Ho?KftXsN5x2|q$v*g|5xn+;t z7hhV|)T-cx$36e-yMqfav~AAV&~ri!0Qd| z%7ZZ|8F6yRglGY_JwBPC|a4 zk39%JUa8h~h~Q#eDiIx1HFY0lVuAEM1vdSaIFw|cWdRT;p^=B5Y5zBn)1PRm4#eZb zi*kU;`1phhY_B+kC=;(_=Wcx_>&pTlW~u=8Q`(2?YO1GANxYBOXA-=_450Xv&eC{&-zJ(kn;A8*^~WtlAi+AcM;wK`x0&#{wXawSvX+tv0?lR?e{kn@V zos4~~F!dN6LIn!g=k^6on*lZjfC!dKM!%p7^)LX-agOh{dV(LUfY^)-n6phMqeF_q zx{0UTlfTpI34Ek(CIA5>m57b1nnt^Z(JhE?84N5%X@a%u*Ifg}&Q@+c4a4H~OApZ( zi}j`W4FezoOvdBWOhxeuUUl!wU^WzhaGZ|EFFO>cpXy?trc{U@l7Dym6aOcFm!sw4 Q3IG5A07*qoM6N<$f)550+5i9m literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-loading@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-loading@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..a0afb37b4ab4186b526ede1511d40cf6fc4f99e3 GIT binary patch literal 569 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 literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-success@2x.png b/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe-success@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..d2549fa7d7a9a01f00d4a19d60a9f43d7e981924 GIT binary patch literal 1040 zcmV+r1n>KaP)Px&%1J~)R9Fe^R$WLGQ53#+cD2=1jLO-}%u4!&sOZlk(;$k9!h$5IStFyTB#TJh zhknpqwJ`dDC?eL)ptdN%=;xt7>F1^Bp$8#*sIb!22l1z|nw`_R*lgSEomt&AdTCzn zz2|)AobR4<_S_}pAAfYD<7eMFJ*uy>e;=U$?NUW;B>zGrz;N_=j~-cjJNtYpsMV?p z0T5a~zVHIT#z@#uy(s}j{%Asq7=AaVwC->&T(_h$sl4BR~o&oDw}%l^xPSe~Kk3 zk5JOg4`D8ij=(RU*ep)5-gRMqyuCj$Gkp!thuh}i!nH9GVD7Llb~nqd*R66d%*xCu zpj2pJa-49sEMKji?ajWJ2{7mQ3n{>7_s{0TI)OnF zu(C(#eKO_xaS`8-5<-O|YF*;NW?akUxlc#ylC`dg^zoJhwNv7j-zCXRtsLUMU_+(kRxui}f~PuOWN& z@R3Q<14GaFmun}U7lg|6d%S%M5}3{8zi#ithD{&>J?xh%j%oNX0-C~X&AN3mRqm1R zp~EGHIGm7vN5u?HKfzO-8=!$Eyj%*_y|BH=>0>%h4`?RF>-&Pz?$lJvYW%G|HAelZ z`BGHYY$ZY-X6Dw+$;)nP+Nd(18H?WIqY3|TP7dMHzEXBpjQj` z{Ft4YQ%DKDI+VZ~X2b|EhmZ5~mE6Sa?Np$}7D_6$Apcjh4EzM15K%7Spd_dO0000< KMNUMnLSTX{4EB-$ literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..08f977793e8a2b4fe2fe5a8f589f0830241d3fa6 GIT binary patch literal 530 zcmV+t0`2{YP)Px$%t=H+R5%f(QqM~pK@@(oyVY2=k)*V}REm&WA>Hh{KeWX?ltw}A#druk73?v_ zs|O4H3wo$0Pq~OEk5NmZmz5e!Z9Pgs54i|}DK^k3JM+3jJL^P3Q|Z9)zW43-eUD)u zz<(a~U;PKE1x-UJ?i^;rhj?7R--(wSXndi7A01*iSKK$Nj zesEnk!3DbMOfaMcKv?Ge)e{Bea=ET-HhXiRFSZzpHhx~9pB}bfFof6rJvW{c0*$L? z-fM#Vc368G&YuDxCyJuJ0!mMjK}l6r&-eZMBhwMmmKp_cRwZP9Z+BdB;%>O ziFk(JF48kb0Q0)x6n=~8C?#5wbZgJTeR*RTPKNVDB(Il0G=Kl| z_D9>ExK*iaoOKM~0xmwM^>Vn0{RnE22gt*sC&;9X`J`|=$ARDxQLybc%KB^LUmvQP UOx|Rz82|tP07*qoM6N<$f>-A7YybcN literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@2x.png b/packages/client-app/internal_packages/unsubscribe/assets/toolbar-unsubscribe@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..22f9c587a0226c349ab308e37c722cdf1ce42dc5 GIT binary patch literal 1114 zcmV-g1f~0lP)Px(6iGxuR9Fe^R!wXhMHGHBHaH@R_)kNlf>IjPLj-o#>)1{Tivl7_A*DhU7bvI) zBqYS4M>r4;aN>f>0aZX%(F(N@v?7S0(nfBmz4rPq7Kcc^REU70qC!PN?IhkEz7cjX zyI$LAEOF^dtC@N4oAY6O z=GU~ln&G7Wv0x-5h`z?ZSCANJWllo^larG?5R4q9I8G&*>tsf-Dju44% z%PhwR)yRJw1ftQ0R;~5(Oo%Sv_GU7A-pyG(c|!tn0%J@RGRZg5zKda}CB(E}4ZkXN zs;c#fRqH$n+9t@ee?F6pOZjF#uN|yunzvXi-dii@od2oo`eZ-}Uju;;;qVx;eb<^O z?PHAki1PylBXO>FPOE)K1Xfnoc9+VuRQng##DbzkcIUInBgE+-qEW`_cpFJKz=$0x z82Xu39olgY0viBEKO_EM$zL$anj{Vn4-a=0(y0@iv;81Z{0A#kc~m#%ZL;Iog6e!G z*xY-BhX}aKAo8J64#KXSCJDh zUtcMG2@)Mmra9C%O+Z?bN6zQ*?m-^>gl(9(zFhn^93Jm-cxfQm5&>z~FfLv8c{@fx zVgV)i$yM|B3l01^R9hw>Ev8bj#oIlddytrEA*gP(ba<`^+Co6uGK>q?I(?o|bZ0BJ z`(;h3^j({_5s)6@@%Zxg?t8|u9cNG@Mv)U|73H}*T)jilRszz|%*@Pc|IQr;upP(b zwOpp(W)(%d&y9qmfCPilfpua2h*kUo1FjbfXY6b~qkme@u&R#iG>jjv_|?baA&-QBl;dlEZs(Y+Tv?in+H{|VI zrBhQ=CIDA!L3R4mgQ4iNmT6AI*=H!l<@t2-WEF?7;$igfhfD0^K{fn`Wr@#mw>$yO z_f@SU0#!w`HfJPe8Rz4`6|uVGaPZ>B9E4}1U+Lu1$y40xeZ0SK$2+yUn+5PgWvafwkcnX0xeFc(6Q!C)*8F!7u#5=)TQd&s&N> zbs2dhp$pPx%F-b&0R5%f1U>LT**w}?%-^?-)n+FX{%)QLb&Bc-Bn2#Kg0i-Ao|6#C+9(i{%82NoPm+C z^1_+pQ<3!(Z7@g^$S|1U5|T0!42=KVz=oba-h*r?h|P#BU|?b~56D-8Nc_K|q9~WQ zdiCmG$Z9}r17nM6K$mAQGBB>baP~wvx;%)F62||5dVu&d{*L#&a0{GsZEpGaf}Y z7==wJC{Pp=;1KO%0_I>yv!IJGGW>S}Mj$J)I3pwDPf1aMN!zz?{|OT}aBvW~aNxiP z7$2QRaWUh6hKs-i&&|ll;DL-882;5ffBk-4XlN)K%mBvEKavbgEmC28bQ&dtpi9E| zM&{0xCYj{9iBR?Ack6B=_&X5-{?zVCs-*6c-~)AhXY%Jb9LhiNy(+v@HKH zURvSc;J^Z8<8>5K27@d)f9lA^|4ht|K&JJF&p(y|jm3x`WXBL~Fi6wI(?_qeGBDc% znKu9b{Vzo}2%Sxm!640N&K$kT#Kve3EZM%G8%7nrr>7^orKKe&RSYA=5CBE@vXmdW Rq=*0j002ovPDHLkV1nX8BWeHu literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-error@2x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-error@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..2d9f1397d12937a0a689568a975265e6c8b56cb5 GIT binary patch literal 1075 zcmV-31kC%1P)Px&?MXyIR9Fe^m`zL*K@@=Bv_K&e0~(_Te?TSvL{dr%ZTX2!hzFwaFPeD3gB~TC zc=F1@lZlB36BDBsJ$S%qI4B{4=>-ab6%HOG!9ZvgZ(G$A2u0!>OP`wjZ70nJ@%ux~ zYa5Fny)D5WBOhU;w4>uJF)RSqlK;8@_xTxV?3Gb0hTQ-dW*;Gh>?#+B-^F5cT0V|v zcw%C3S%B*@!_rlOAiprmbS^B}qd>T>2g?uOc!oJBH-=Q>ODnQ1kw3qXyYjTHWmxtrOFQS?k|1{j!qq$l31wJ0<7;p4 zo*o_jmao^Aq?W;EW))x=!SzMkT3>2rTSFmWIrpNUvkv3(ps%fMpML19Ci8-&mjP*L z2}4<-EiW4(+tbZ()Gdeia^9*Yw!fXDz)V^1EB># z+*vN%jZ;%&@6~#vvB@Q26k<~si^W!Jsw+>^k^DL(K{%91u8#ORJ9p%HqyDE^o~=sY z7%<0;Mx*hD`aS39>tuk(2yis{GcnTI+O?g>PBce>8K}R%f8CAViv<0A6A&BMlPkj= z9UWY~r5de6+e^`LU?!5Jhlz&zy_X338IS2@Y+6}OylIL=YIsbNe+!tADAV%UQ{6oT z{Un75;D?p?Q0gyL+D2Grrxhi`3P@jHUy`7&5Z@z~(GJqOCNB-rJIDXG*=n|*)XHoG zDtv+PeL66%<@){AZ7ml>-KVV%XQc67S|0b*I;-QNE(tZv%+v&bI^9vrt&IODFoRLi tbIav%*LmEY{fNhAt-zLSOBv9}z%R~{vp=SlBP;*_002ovPDHLkV1m<0{{;X5 literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..f6923f07b7fb77f6cf3ae22da90f8df5e75adad0 GIT binary patch literal 654 zcmV;90&)F`P)Px%NJ&INR5%gMR6%PKQ4pTlO&W_J@gP`4(NM*cS#6SLsWvgan7j1{2woJ#gW^Sc z@}fs?dhk*NA)pr_c#+V9FOjTi)k6nKG5HC-!SPWAkH%3cQoLZN$En6G>m7UXJzag)>MAI zTrMZ1X%&mffgukN^WV=N!n=b+uYh2EZLOWtg9NyW1R1SZaLLhyhull)IURk9cR+$#%V|8& z13D(mtifTi(Ww41<3@?ykN~13*^&z; zz2KQa#lZZ>&O57fpJKMt3g4>ze5)>bH-DrBcEF4I`S~$@5IfzgRyKc4*TER+Uy;t( zIVATrKXl2YGnXCb$rfAgHn@~pcIwxIq*D774;v6{rK#S<&?o`W%r<^_UMv=4e1Sqm zMIsjRW>d9HGA=UV`HfEZ8Pg7YADPoDGO-+R9Q82Gv?gJ!A3%(l>C=WTO!L1tzb_7xE0ke*gdg07*qoM6N<$f|-gf-2eap literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@2x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-loading@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..cd3cb35d33c1e53fffd800e8f9ea15389ea98d8d GIT binary patch literal 1223 zcmV;&1UUPNP)Px(fk{L`R9Fe^SWk!>RTzISligTrOINWfXx&v>QCv4MX_8HLHL{lmDceJlO7&t7 z^`b=&?M3Lhlp=T$#05d>!BwO!5{uoEgZa0c*-cT=q6ZbVrJ_sQ&}Ng&e16|dhK4tp z*_kn8d&odC@B9Co?|tvRZ-%kKHORp2&A>z~c{(0{ZpwGt^Bd6< z(F7pcGg6QpSuU4nARI64}qK-&A$*^eSfR>Jt5&>zm_NN3)G$J0! zNJp3HHlm(LTh_3s=!ULUi>JcT?h%mAv63EH);;^H5-BrC9vcP9IObjMpaKVMzdfKUn{VC)wj_Q#qeV zWFEEyjCvnOqRBVybgX2S-I`ScZ{-L(of$lMqa?@U_Gf;V^t@HSjGf>mJf$BDvcQwF zT>8<{XAglT;2yfRtaLiPsorRRiAvL&B4-ze`G(BWQvR}Nh@Y!2;{!f0#HI0SwfLPV zx1$}Fgq;grRwxv%2iewLNS)U>z@BKSHy0w))AyUK@x9r^bI9l$V2UTpXKsva+VCR2 zettzXmdI1;jn)G75k&Xn>MLLZl+WiIJH{TF#W&{DIzSk2s`YbIQ&S@bU`+3wkzoVS z{QP`Vf@k((3;7xGupbWBZ??V;XEIxK9k{aq6DV2!ptXH$+dkYev`aR?XUagpza{$BwTF#K3@I1rLXLsIB5 lfTu6I0XxtgWS~a|{sm5|kx1}~E|CBL002ovPDHLkV1g5uO)LNa literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-success@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe-success@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..c8440864975497e47852d3301a9ca708320c6ef4 GIT binary patch literal 660 zcmV;F0&D$=P)Px%PDw;TR5%gMluc+8Q4q&x_N`5$mnb!xlz=FSCl7w$$&x_*IBD@>51~ZCn}|0L zw&x^%;XxEnO0(Kal;A~0p`gWF6c0iVg1rf$Et)7|6O!zk&T1dYhTUXKFD@+a?acrG z+j;NJF2MhGjn3vz8D@Umt1itgajsYtvALTGx11d_%xt<1@)ZzW^wPM37wTUxH(Tvb z;m6sNy+&g;H$emij=Or5-ZhyFChj4^GqCVQxR9MvVxy2h!Sf;z=qlzlx(c37PFlpv zj25m}C4d<*bE6t+?=2~x6Hvel)*W|%jY94bFLS>wh?x1sk?rv--|I_NDd`5G)#Thz zx4GZk0VaTh0CdPUFyt6R6QPheTl*!eB<1~npx&J89xD-V$9S#Qev6=&5VbS_wp4D= z*cZHEK1|dq1L_}yzzGCc8w9oUe!%v=#EF_^KD>$$!fwHzgW&$aHiaO{_d5b9P!~zw zmSygcnEf%iy~IEGpF1QidIN2_Hvsw=62=zlOQl%xPOulgSuht3!-P<3qLmsJ!7&Ez zYtQ@ZII$KsHm9NxGAs=siddB u3<*r}QongYw-k@Ryc=-q-z`D?nAZVmp4G7YV$f6o0000Px)I7vi7R9Fe^n0;(hRTRMQeQh^8*_>mp-57JgkW9p2B7TJcQ)7f>K?62Uu$`hI z3t^}U)3(MKWc`>Q#2FGLF|OSPri))lCc;2w-2U({{}7{L8WP#EPHsM{ zoC=g*%d(o@g|xT~245-&`7aU9_Mvgk*#4nmwhOw2C>zmKfgwVem(M3Vg-ww07~8z~ zNO0qy)vxvsy4-Ks!wr8kPCtPBpoAL-i!7RR7#Bf0+&wWN_7t@QSD-xL^d6*?ZzqJt zQ8u!r1&lyYlW&)p)NKz1??XB2^d1%j@&u$x3}vHQ+Q0||kzUA&bh@b7{}{^n1u{_q z`f`5bknU|(z(|8-O(gu7t=V6VGTy!{7V`#5XcT3=+pK{nfw+ZJ-ewE?>QL_6R{xX5 zMAriJ`N?_xK6L^HAgB0Mu=Q@LySCn1=730loPdT+ zy}aV9pr%W`p}^O{R+BjCwzc_}wmTeBw8rxSMEV_hL!3W4G%R)DRWz}QRL{8phWsGQ zNSya9YHM7LK!YyNUMf(x49EFBu~@ukQOI{kDp;JK8(?sRZyj+l-i2?@=s4>11Sk=9 zLYF~mEP)@NZm8q;d62FQAPItSB3srDw8iyL5#hCOZ%x_^q-o72d$RcJew^;AF*A^2*4;1s7wNkAXuuM^owJJQc_) zxR(B$(6xmd?t)F9fMbx~SRm>j!3osD6M{e4bjxA0CB?Ajl4r>{{R30 M07*qoM6N<$g1Q5(I{*Lx literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@1x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@1x.png new file mode 100755 index 0000000000000000000000000000000000000000..e20f0cadecf77af31d3fbb68b646ce10aad61c0b GIT binary patch literal 749 zcmVPx%r%6OXR5%gMlR;<`Q4ogby-n3p#2)mZ)F_1(MKqfxX|k!bQ8XB+#e=y>pevw!{rHvo0@|sOU1?Q9MNc05dHoJJD+Y7J<r~q z0N}aB{EtD@pt^`=GHe?B2QCj$HRvVSLKoaHaf-GTfpv9eTpksGw*tc)%{slAil}6$ z7_37SMSkZ%;W#~X9aT+SlBA-vP#>%hmp3p;6)}&%M%JxBCCrxh?y0?%?Obmr; zg}hq5$_hyan6Iwl?XoN{7&=SD3}K2WHH^U-^90mx&dulI^xNAEA0gs(ml>P#B-ZkpV`izpg6b^@LK7aWdC;sj! zCFRjsmWWHi^_(IXPEbz$tL*JVs$*&vy5{dlCX-7I_0F?ZjCUEfHK$=Hw^HPXRM1{g z)<=M|3`M+OkJwJLsfZ0BMgD;ryN$kEP{Zqn-EOT2tOGJ*V_B->Hmc!ocEBy$B9X{; fyZYTS_+NlukOuKepSgP$00000NkvXXu0mjfog-GG literal 0 HcmV?d00001 diff --git a/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@2x.png b/packages/client-app/internal_packages/unsubscribe/assets/unsubscribe@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..d2eaaeeef5725902958fdae3127eaffae522fe9e GIT binary patch literal 1587 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 X;6HOGn2*BTgkr&7YC>xj%) { + if (error) { + this.threadState.condition = ThreadConditionType.ERRORED; + NylasEnv.reportError(error, this); + } else if (unsubscribed) { + this._moveThread(); + this.threadState.condition = ThreadConditionType.UNSUBSCRIBED; + } + this._triggerUpdate(); + }; + + if (this.parser.emails.length > 0) { + this._unsubscribeViaMail(this.parser.emails[0], unsubscribeHandler); + } else { + this._unsubscribeViaBrowser(this.parser.urls[0], unsubscribeHandler); + } + } + } + + _loadLinks() { + this._loadMessagesViaAPI((error, email) => { + if (error) { + this.threadState.condition = ThreadConditionType.ERRORED; + NylasEnv.reportError(error, this); + } else if (email) { + const confirmText = "Are you sure that you want to unsubscribe?"; + this.isForwarded = this.thread.subject.match(/^Fwd: /i); + this.confirmText = this.isForwarded ? `The email was forwarded. ${confirmText}` : confirmText; + + this.parser = new EmailParser(email.headers, email.html, email.text); + this.threadState.condition = this.parser.canUnsubscribe() ? ThreadConditionType.READY : ThreadConditionType.DISABLED; + // Output troubleshooting info + logIfDebug(`Found ${(this.parser.canUnsubscribe() ? "" : "no ")}links for: "${this.thread.subject}"`); + logIfDebug(this.parser); + } else { + this.threadState.condition = ThreadConditionType.DISABLED; + } + this._triggerUpdate(); + }); + } + + _loadMessagesViaAPI(callback) { + if (this.messages && this.messages.length > 0) { + if (this.messages[0].draft || (this.messages[0].categories && + _.some(this.messages[0].categories, _.matcher({displayName: "Sent Mail"})))) { + // Can't unsubscribe from draft or sent emails + callback(null, null); + } else { + // Fetch the email contents to parse for unsubscribe links + // NOTE: This will only make a request for the first email message in the thread, + // instead of all messages based on the assumption that the first email will have + // an unsubscribe link iff you can unsubscribe from that thread. + const messagePath = `/messages/${this.messages[0].id}`; + NylasAPI.makeRequest({ + path: messagePath, + accountId: this.thread.accountId, + headers: {Accept: "message/rfc822"}, + json: false, + success: (rawEmail) => { + const mailparser = new MailParser(); + mailparser.on('end', (parsedEmail) => { + callback(null, parsedEmail); + }); + mailparser.write(rawEmail); + mailparser.end(); + }, + error: (error) => { + callback(error); + }, + }); + } + } else { + callback(new Error('No messages found to parse for unsubscribe links.')); + } + } + + _unsubscribeViaBrowser(url, callback) { + if ((!this.isForwarded && !this.settings.confirmForBrowser) || + userConfirm(this.confirmText, `A browser will be opened at: ${shortenURL(url)}`)) { + logIfDebug(`Opening a browser window to:\n${url}`); + if (this.settings.defaultBrowser === "native" || electronCantOpen(url)) { + open(url); + callback(null, /* unsubscribed=*/true); + } else { + const browserWindow = new remote.BrowserWindow({ + 'web-preferences': { 'web-security': false, 'nodeIntegration': false }, + 'width': 1000, + 'height': 800, + 'center': true, + "alwaysOnTop": true, + }); + browserWindow.on('closed', () => { + callback(null, /* unsubscribed=*/true); + }); + browserWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => { + // Unable to load this URL in a browser window. Redirect to a native browser. + logIfDebug(`Failed to open URL in browser window: ${errorCode} ${errorDescription}`); + browserWindow.destroy(); + open(url); + }); + browserWindow.loadURL(url); + browserWindow.show(); + } + } else { + callback(null, /* unsubscribed=*/false); + } + } + + _unsubscribeViaMail(emailAddress, callback) { + if (emailAddress) { + if ((!this.isForwarded && !this.settings.confirmForEmail) || + userConfirm(this.confirmText, `An email will be sent to:\n${shortenEmail(emailAddress)}`)) { + logIfDebug(`Sending an email to: ${emailAddress}`); + NylasAPI.makeRequest({ + path: '/send', + method: 'POST', + accountId: this.thread.accountId, + body: interpretEmail(emailAddress), + success: () => {}, + error: (error) => { + NylasEnv.reportError(error, this); + }, + }); + // Send the callback now so that emails are moved immediately + // instead of waiting for the email to be sent. + callback(null, /* unsubscribed= */true); + } else { + callback(null, /* unsubscribed= */false); + } + } else { + callback(new Error(`Invalid email address (${emailAddress})`), /* unsubscribed= */false); + } + } + + _moveThread() { + switch (this.settings.handleThreads) { + case "trash": + if (FocusedPerspectiveStore.current().canTrashThreads([this.thread])) { + const tasks = TaskFactory.tasksForMovingToTrash({ + threads: [this.thread], + fromPerspective: FocusedPerspectiveStore.current(), + }); + Actions.queueTasks(tasks); + } + break; + case "archive": + if (FocusedPerspectiveStore.current().canArchiveThreads([this.thread])) { + const tasks = TaskFactory.tasksForArchiving({ + threads: [this.thread], + fromPerspective: FocusedPerspectiveStore.current(), + }); + Actions.queueTasks(tasks); + } + break; + default: + // "none" case -- do not move email + } + Actions.popSheet(); + } +} diff --git a/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-buttons.jsx b/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-buttons.jsx new file mode 100755 index 000000000..a58891c49 --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-buttons.jsx @@ -0,0 +1,162 @@ +import {React} from 'nylas-exports'; +import {RetinaImg, KeyCommandsRegion} from 'nylas-component-kit'; +import ThreadUnsubscribeStoreManager from '../thread-unsubscribe-store-manager'; +import ThreadConditionType from '../enum/threadConditionType'; + +const UNSUBSCRIBE_ASSETS_BASE_URL = 'nylas://unsubscribe/assets/'; + +class ThreadUnsubscribeButton extends React.Component { + + static containerRequired = false; + + constructor(props) { + super(props); + this.state = { + condition: ThreadConditionType.LOADING, + hasLinks: false, + }; + this.onClick = this.onClick.bind(this); + } + + componentWillMount() { + this.load(this.props); + } + + componentWillReceiveProps(newProps) { + this.load(newProps); + } + + componentWillUnmount() { + return this.unload(); + } + + onMessageLoad(threadState) { + this.setState(threadState); + } + + onClick(event) { + this.tuStore.unsubscribe(); + event.stopPropagation() + } + + getIconInfo(name : string, ratio : number) { + let url = UNSUBSCRIBE_ASSETS_BASE_URL; + let buttonTitle; + let extraClasses; + let scale = ratio; + + if (typeof scale === 'undefined') { + scale = Math.ceil(window.devicePixelRatio); + if (scale !== 1 || scale !== 2) { scale = 2; } + } + + url += name; + switch (this.state.condition) { + case ThreadConditionType.UNSUBSCRIBED: + extraClasses = 'unsubscribe-success'; + buttonTitle = 'Unsubscribe (Success)'; + url += '-success'; + break; + case ThreadConditionType.ERRORED: + extraClasses = 'unsubscribe-error'; + buttonTitle = 'Unsubscribe (Error)'; + url += '-error'; + break; + case ThreadConditionType.DISABLED: + extraClasses = 'unsubscribe-disabled'; + buttonTitle = 'Unsubscribe (Disabled)'; + url += ''; + break; + case ThreadConditionType.READY: + extraClasses = 'unsubscribe-ready'; + buttonTitle = 'Unsubscribe'; + url += ''; + break; + default: + extraClasses = 'unsubscribe-loading'; + buttonTitle = 'Unsubscribe (Loading)'; + url += '-loading'; + break; + } + + url += `@${scale}x.png`; + + return {buttonTitle, extraClasses, url}; + } + + load(props) { + this.unload(); + this.tuStore = ThreadUnsubscribeStoreManager.getStoreForThread(props.thread); + this.unlisten = this.tuStore.listen(this.onMessageLoad.bind(this)); + this.tuStore._triggerUpdate(); + } + + unload() { + if (this.unlisten) { + this.unlisten(); + } + this.unlisten = null; + this.tuStore = null; + } + + render() { + return null; + } +} + +export class ThreadUnsubscribeQuickActionButton extends ThreadUnsubscribeButton { + + static displayName = 'ThreadUnsubscribeQuickActionButton'; + + render() { + const {buttonTitle, extraClasses, url} = this.getIconInfo('unsubscribe'); + return ( + + + ); + } + + _keymapEvent() { + const e = document.getElementById('unsubscribe'); + e.click() + } +} diff --git a/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-preferences.jsx b/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-preferences.jsx new file mode 100755 index 000000000..4a38e4293 --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/lib/ui/unsubscribe-preferences.jsx @@ -0,0 +1,46 @@ +import {React} from 'nylas-exports'; +import ConfigSchemaItem from '../../../preferences/lib/tabs/config-schema-item'; +import CommandItem from '../../../preferences/lib/tabs/keymaps/command-item'; + +class UnsubscribePreferences extends React.Component { + + componentDidMount() { + this._disposable = NylasEnv.keymaps.onDidReloadKeymap(() => { + this.setState({binding: NylasEnv.keymaps.getBindingsForCommand('unsubscribe:unsubscribe')}); + }); + } + + componentWillUnmount() { + this._disposable.dispose(); + } + + render() { + return ( +
+ +
Keymaps
+
+ +
+
+ ); + } +} + +UnsubscribePreferences.displayName = 'UnsubscribePreferences'; +UnsubscribePreferences.propTypes = { + config: React.PropTypes.object, + configSchema: React.PropTypes.object, +}; + +export default UnsubscribePreferences; diff --git a/packages/client-app/internal_packages/unsubscribe/lib/util/blacklist.es6 b/packages/client-app/internal_packages/unsubscribe/lib/util/blacklist.es6 new file mode 100755 index 000000000..9873f77d7 --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/lib/util/blacklist.es6 @@ -0,0 +1,38 @@ +import _ from 'underscore'; + +const blacklistExpressions = { + // Electron has Jquery and other limitations that block certain known URLs + urls: [ + /www\.roomster\.com/, + /trulia\.com/, + /hackerrank\.com/, + /www\.apartmentlist\.com/, + /\/wf\/click\?upn=/, + /timbuk2\.com/, + /perch-email\.closely\.com/, + /aore\.memberclicks\.net/, + /www\.cybercoders\.com/, + /links\.notifications\.soundcloud\.com\/asm\/unsubscribe/, + /fullcontact\.com/, + /www\.facebook\.com/, + /ke\.am\//, + /email\.newyorktimes\.com/, + /github\.com/, + ], + // Some emails are known to fail or require a custom body message + emails: [ + /@idearium.activehosted.com/, + /sympa@/, + /@blancmedia\.activehosted\.com/, + /@bounce/, + /unsubscribe@mail\.notifications\.soundcloud\.com/, + ], +} + +export function electronCantOpen(url) { + return _.some(blacklistExpressions.urls, (re) => re.test(url)); +} + +export function blacklistedEmail(email) { + return _.some(blacklistExpressions.emails, (re) => re.test(email)); +} diff --git a/packages/client-app/internal_packages/unsubscribe/lib/util/email-parser.es6 b/packages/client-app/internal_packages/unsubscribe/lib/util/email-parser.es6 new file mode 100755 index 000000000..a350b24bf --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/lib/util/email-parser.es6 @@ -0,0 +1,177 @@ +import cheerio from 'cheerio'; +import {blacklistedEmail} from './blacklist'; + +const regexps = [ + // English + /unsubscribe/gi, + /unfollow/gi, + /opt[ -]{0,2}out/gi, + /email preferences/gi, + /subscription/gi, + /notification settings/gi, + /Remove yourself from this mailing/gi, + // Danish + /afmeld/gi, + /afmelden/gi, + /af te melden voor/gi, + // Spanish + /darse de baja/gi, + // French + /désabonnement/gi, + /désinscrire/gi, + /désinscription/gi, + /désabonner/gi, + /préférences d'email/gi, + /préférences d'abonnement/gi, + // Russian - this is probably wrong: + /отказаться от подписки/gi, + // Serbian + /одјавити/gi, + // Icelandic + /afskrá/gi, + // Hebrew + /לבטל את המנוי/gi, + // Creole (Haitian) + /koupe abònman/gi, + // Chinese (Simplified) + /退订/gi, + // Chinese (Traditional) + /退訂/gi, + // Arabic + /إلغاء الاشتراك/gi, + // Armenian + /պետք է նախ միանալ/gi, + // German + /abmelden/gi, + /ausschreiben/gi, + /austragen/gi, + // Swedish + /avprenumerera/gi, + /avregistrera/gi, + /prenumeration/gi, + /notisinställningar/gi, +]; + +export default class EmailParser { + constructor(headers, html, text) { + this.emails = []; + this.urls = []; + this.__headers(headers); + this.__html(html); + this.__text(text); + } + + canUnsubscribe() { + return this.emails.length > 0 || this.urls.length > 0; + } + + __headers(headers) { + if (headers) { + const unsubHeader = headers['list-unsubscribe']; + if (unsubHeader && typeof unsubHeader === 'string') { + unsubHeader.split(',').forEach((link) => { + this.__addLink(link.trim().replace(/^<|>$/g, '')); + }); + } + } + } + + __html(html) { + if (html) { + const $ = cheerio.load(html); + const links = this.__getLinks($); + + for (const link of links) { + for (const re of regexps) { + if (re.test(link.href) || re.test(link.innerText)) { + this.__addLink(link.href); + } + } + } + } + } + + __text(text) { + if (text) { + const ext = /[^\s]*/ig; + for (let i = 0; i < regexps.length; i += 1) { + const re = RegExp(`${ext.source}${regexps[i].source}${ext.source}`, 'ig'); + const matcher = text.match(re); + if (matcher) { + this.__addLink(matcher[0].replace(/(?:\.|!)$/g, '')); + } + } + } + } + + __addLink(link) { + if (/mailto:[^>]*/g.test(link)) { + if (!blacklistedEmail(link)) { + this.emails.push(link); + } + } else if (/https?:.*/g.test(link)) { + this.urls.push(link); + } + } + + // Takes a parsed DOM (through cheerio) and returns links paired with contextual text + // Good at catching cases such as: + // "If you would like to unsubscrbe from our emails, please click here." + // Returns a list of links as {href, innerText} objects + __getLinks($) { + const aParents = []; + $('a').each((index, aTag) => { + if (aTag && aTag.parent && !$(aParents).is(aTag.parent)) { + aParents.unshift(aTag.parent); + } + }); + + const links = []; + $(aParents).each((parentIndex, parent) => { + let link = false; + let leftoverText = ""; + $(parent.children).each((childIndex, child) => { + if ($(child).is($('a'))) { + if (link !== false && leftoverText.length > 0) { + links.push({ + href: link, + innerText: leftoverText, + }); + leftoverText = ""; + } + link = $(child).attr('href'); + } + const text = $(child).text(); + const re = /(.*[.!?](?:\s|$))/g; + if (re.test(text)) { + const splitup = text.split(re); + for (let i = 0; i < splitup.length; i += 1) { + if (splitup[i] !== "" && splitup[i] !== undefined) { + if (link !== false) { + const fullLine = leftoverText + splitup[i]; + links.push({ + href: link, + innerText: fullLine, + }); + link = false; + leftoverText = ""; + } else { + leftoverText += splitup[i]; + } + } + } + } else { + leftoverText += text; + } + leftoverText += " "; + }); + if (link !== false && leftoverText.length > 0) { + links.push({ + href: link, + innerText: leftoverText, + }); + } + }); + return links; + } +} diff --git a/packages/client-app/internal_packages/unsubscribe/lib/util/helpers.es6 b/packages/client-app/internal_packages/unsubscribe/lib/util/helpers.es6 new file mode 100755 index 000000000..efb0d6ec0 --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/lib/util/helpers.es6 @@ -0,0 +1,59 @@ +import {parse} from "mailto-parser"; +import {remote} from 'electron'; + +const MAX_USERNAME_LENGTH = 15; +const MAX_DOMAIN_LENGTH = 25; + +export function logIfDebug(message) { + console.debug(NylasEnv.config.settings.devMode, message); +} + +export function shortenURL(url) { + const regex = /^(?:[^:/?#]+:?\/\/([^/?#]*))/i; + const disURL = regex.exec(url)[1]; + return `${disURL}/...`; +} + +export const defaultBody = 'This is an automated unsubscription request. ' + + 'Please remove the sender of this email from all email lists.' + +export function interpretEmail(emailAddress) { + const parsedEmail = parse(emailAddress); + const email = { + body: parsedEmail.attributeKey.body || defaultBody, + subject: parsedEmail.attributeKey.subject || "Unsubscribe", + to: [{ + email: parsedEmail.to, + }], + } + if (parsedEmail.attributeKey.cc) { + email.cc = [{ + email: parsedEmail.attributeKey.cc, + }]; + } + if (parsedEmail.attributeKey.bcc) { + email.bcc = [{ + email: parsedEmail.attributeKey.bcc, + }]; + } + return email; +} + +export function shortenEmail(email) { + const address = interpretEmail(email).to[0].email; + const parts = address.split('@', 2); + const shortUsername = parts[0].length > MAX_USERNAME_LENGTH ? `${parts[0].substring(0, MAX_USERNAME_LENGTH - 3)}...` : parts[0]; + const shortDomain = parts[1].length > MAX_DOMAIN_LENGTH ? `${parts[1].substring(0, MAX_DOMAIN_LENGTH - 3)}...` : parts[1]; + return `${shortUsername}@${shortDomain}`; +} + +export function userConfirm(message, detail) { + const chosen = remote.dialog.showMessageBox(NylasEnv.getCurrentWindow(), { + type: 'info', + message: message, + detail: detail, + buttons: ['Cancel', 'Unsubscribe'], + }); + + return chosen === 1; +} diff --git a/packages/client-app/internal_packages/unsubscribe/package.json b/packages/client-app/internal_packages/unsubscribe/package.json new file mode 100755 index 000000000..a7a9b253b --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/package.json @@ -0,0 +1,24 @@ +{ + "name": "unsubscribe", + "version": "2.0.0", + "main": "./lib/main", + "description": "Unsubscribe without leaving N1.", + "license": "GPL-3.0", + "title": "Unsubscribe", + "icon": "./icon.png", + "isOptional": true, + "repository": { + "type": "git", + "url": "https://github.com/nylas/N1" + }, + "engines": { + "nylas": "*" + }, + "dependencies": { + "cheerio": "^0.22.0", + "mailparser": "^0.6.1", + "mailto-parser": "^1.0.0", + "open": "0.0.5", + "underscore": "^1.8.3" + } +} diff --git a/packages/client-app/internal_packages/unsubscribe/plugin.png b/packages/client-app/internal_packages/unsubscribe/plugin.png new file mode 100755 index 0000000000000000000000000000000000000000..5faffe6b7f6af359813b6df13f3889f54f476ad6 GIT binary patch literal 27974 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 m8D19z|9^zG`aSd&u6I?xO|NLX6!519Sa { + expect(electronCantOpen("https://github.com/unsubscribe")).toBe(true); + expect(electronCantOpen("https://test.com/wf/click?upn=iwbeg538ht938h3gnio")).toBe(true); + expect(electronCantOpen("https://test.com/unsubscribe")).toBe(false); + }); + it("blacklistedEmail", () => { + expect(blacklistedEmail("mailto:sympa@test.com")).toBe(true); + expect(blacklistedEmail("mailto:test@test.com")).toBe(false); + }); +}); diff --git a/packages/client-app/internal_packages/unsubscribe/spec/util/email-parser-spec.es6 b/packages/client-app/internal_packages/unsubscribe/spec/util/email-parser-spec.es6 new file mode 100755 index 000000000..10c262dbf --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/spec/util/email-parser-spec.es6 @@ -0,0 +1,62 @@ +import EmailParser from '../../lib/util/email-parser'; + +describe("EmailParser", function emailParser() { + describe("__headers", () => { + it("parses single email link", () => { + const parser = new EmailParser({ + 'list-unsubscribe': 'mailto:test@test.com', + }, null, null); + expect(parser.emails).toEqual(['mailto:test@test.com']); + expect(parser.urls).toEqual([]); + expect(parser.canUnsubscribe()).toEqual(true); + }); + it("parses multiple links", () => { + const parser = new EmailParser({ + 'list-unsubscribe': 'https://test.com/unsubscribe, mailto:test@test.com,mailto:test2@test.com', + }, null, null); + expect(parser.emails).toEqual(['mailto:test@test.com', 'mailto:test2@test.com']); + expect(parser.urls).toEqual(['https://test.com/unsubscribe']); + expect(parser.canUnsubscribe()).toEqual(true); + }); + }); + describe("__html", () => { + it("parses simple html without unsubscribe link", () => { + const parser = new EmailParser(null, "Hello!", null); + expect(parser.emails).toEqual([]); + expect(parser.urls).toEqual([]); + expect(parser.canUnsubscribe()).toEqual(false); + }); + it("parses simple html with unsubscribe link", () => { + const parser = new EmailParser(null, "UnsubscribeOpt Out", null); + expect(parser.emails).toEqual(['mailto:test@test.com?subject=testing']); + expect(parser.urls).toEqual(['https://test.com']); + expect(parser.canUnsubscribe()).toEqual(true); + }); + it("parses simple html with unsubscribe link within a sentence", () => { + const parser = new EmailParser(null, "

Opt out of emails here

", null); + expect(parser.emails).toEqual([]); + expect(parser.urls).toEqual(['https://test.com']); + expect(parser.canUnsubscribe()).toEqual(true); + }); + it("discovers multi-lingual unsubscribe links", () => { + const parser = new EmailParser(null, "

Para darse de baja, haga clic aquí

", null); + expect(parser.emails).toEqual([]); + expect(parser.urls).toEqual(['https://test.com']); + expect(parser.canUnsubscribe()).toEqual(true); + }); + }); + describe("__text", () => { + it("parses simple text without unsubscribe link", () => { + const parser = new EmailParser(null, null, "Hello, We regret to inform you that we don't believe in unsubscribing."); + expect(parser.emails).toEqual([]); + expect(parser.urls).toEqual([]); + expect(parser.canUnsubscribe()).toEqual(false); + }); + it("parses simple text with unsubscribe links", () => { + const parser = new EmailParser(null, null, "Just kidding. Visit https://test.com/unsubscribe."); + expect(parser.emails).toEqual([]); + expect(parser.urls).toEqual(['https://test.com/unsubscribe']); + expect(parser.canUnsubscribe()).toEqual(true); + }); + }); +}); diff --git a/packages/client-app/internal_packages/unsubscribe/spec/util/helpers-spec.es6 b/packages/client-app/internal_packages/unsubscribe/spec/util/helpers-spec.es6 new file mode 100755 index 000000000..dbc04de9f --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/spec/util/helpers-spec.es6 @@ -0,0 +1,27 @@ +import {shortenURL, shortenEmail, interpretEmail, defaultBody} from '../../lib/util/helpers'; + +describe("helpers", function helpers() { + it("shortenURL", () => { + expect(shortenURL("http://www.aweber.com/z/r/?HCwMbCwctKzsLJzqHAxMtEa0zCzMTOycrIw=")).toEqual("www.aweber.com/..."); + expect(shortenURL("https://www.aweber.com/z/r/?HCwMbCwctKzsLJzqHAxMtEa0zCzMTOycrIw=")).toEqual("www.aweber.com/..."); + }); + it("shortenEmail", () => { + expect(shortenEmail("mailto:test@test.com")).toEqual("test@test.com"); + expect(shortenEmail("mailto:testing0123456789@test.com")).toEqual("testing01234...@test.com"); + expect(shortenEmail("mailto:test@test.testing0123456789.com")).toEqual("test@test.testing0123456789..."); + }); + it("interpretEmail", () => { + expect(interpretEmail("mailto:thisistrue@aweber.com?subject=unsubscribe;HCwMbCwctKzsLJzqHAxMtEa0zCzMTOycrIw=")).toEqual({ + subject: "unsubscribe;HCwMbCwctKzsLJzqHAxMtEa0zCzMTOycrIw=", + body: defaultBody, + to: [{email: "thisistrue@aweber.com"}], + }); + expect(interpretEmail("mailto:test@test.com?cc=test2@test.com&bcc=test3@test.com&body=end%20subscription")).toEqual({ + subject: "Unsubscribe", + body: "end%20subscription", + to: [{email: "test@test.com"}], + cc: [{email: "test2@test.com"}], + bcc: [{email: "test3@test.com"}], + }); + }); +}); diff --git a/packages/client-app/internal_packages/unsubscribe/stylesheets/main.less b/packages/client-app/internal_packages/unsubscribe/stylesheets/main.less new file mode 100755 index 000000000..d8e375a33 --- /dev/null +++ b/packages/client-app/internal_packages/unsubscribe/stylesheets/main.less @@ -0,0 +1,52 @@ +@import "ui-variables"; +@import "ui-mixins"; +@import "buttons"; + +.action-unsubscribe, +.toolbar-unsubscribe { + &.unsubscribe-disabled, + &.unsubscribe-loading, + &.unsubscribe-error { + opacity: 0.5; + } +} + +// Fix for the opacity gradient behind the quick action icons: +// See: https://github.com/nylas/N1/blob/81d1b36ef2baeb2d10f015b704c2825a39bfc409/internal_packages/ui-darkside/styles/darkside.less#L462 + +// +// Light Themes: +// +body.theme-ui-light .thread-list .list-item:hover .list-column-HoverActions .inner { + background-image: -webkit-linear-gradient(left, rgba(245, 245, 246, 0) 0%, #f5f5f6 20%, #f5f5f6 100%); +} +body.theme-ui-taiga .thread-list .list-item:hover .list-column-HoverActions .inner { + background-image: -webkit-linear-gradient(left, rgba(242, 242, 242, 0) 0%, #f2f2f2 20%, #f2f2f2 100%); +} + +// +// Dark Themes: +// + +.dark-theme-fix(@theme) { + body.@{theme} .thread-list .list-item:hover .list-column-HoverActions .inner { + background-image: -webkit-linear-gradient(left, rgba(38, 38, 38, 0) 0%, #262626 20%, #262626 100%); + } + body.@{theme} .thread-list .list-item:hover .list-column-HoverActions .action.action-unsubscribe { + background-color: RGB(198, 198, 198) !important; + } +}; + +// Supported dark themes +.dark-theme-fix(theme-arc-dark); +.dark-theme-fix(theme-ui-dark); +.dark-theme-fix(theme-n1-monokai); +.dark-theme-fix(theme-levelup); +.dark-theme-fix(theme-N1-Predawn); + +body.theme-arc-dark .thread-list .list-item:hover .list-column-HoverActions .action.action-unsubscribe { + background-color: RGB(37, 143, 225) !important; +} +body.theme-N1-Ido .thread-list .list-item:hover .list-column-HoverActions .action.action-unsubscribe { + background-color: RGB(255, 255, 255) !important; +} diff --git a/packages/client-app/package.json b/packages/client-app/package.json index 6ec559df9..872c3d0a9 100644 --- a/packages/client-app/package.json +++ b/packages/client-app/package.json @@ -22,6 +22,7 @@ "base64-stream": "0.1.3", "better-sqlite3": "bengotow/better-sqlite3#a888061ad334c76d2db4c06554c90785cc6e7cce", "bluebird": "3.4.x", + "cheerio": "^0.22.0", "chromium-net-errors": "1.0.3", "chrono-node": "^1.1.2", "classnames": "1.2.1", @@ -66,6 +67,8 @@ "keytar": "3.0.0", "less-cache": "0.21", "lru-cache": "^4.0.1", + "mailparser": "^0.6.1", + "mailto-parser": "^1.0.0", "marked": "^0.3", "mimelib": "0.2.19", "mkdirp": "^0.5", @@ -77,6 +80,7 @@ "node-emoji": "^1.2.1", "node-uuid": "^1.4", "nslog": "^3", + "open": "0.0.5", "optimist": "0.4.0", "papaparse": "^4.1.2", "pathwatcher": "~6.2", From a8a9ca0278e0cac83b2e45deb09de5d4224c2bc3 Mon Sep 17 00:00:00 2001 From: Kyle King Date: Sat, 15 Jul 2017 01:14:43 -0400 Subject: [PATCH 2/2] fix broken N1 api request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and fix out-of-date “N1” references with “Nylas Mail” --- .../internal_packages/unsubscribe/README.md | 4 +- .../lib/thread-unsubscribe-store.es6 | 54 ++++++++++-------- .../unsubscribe/package.json | 4 +- .../internal_packages/unsubscribe/plugin.png | Bin 27974 -> 29025 bytes .../src/flux/modules/reflux-coffee.coffee | 2 +- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/client-app/internal_packages/unsubscribe/README.md b/packages/client-app/internal_packages/unsubscribe/README.md index dbd947dba..2f392e801 100755 --- a/packages/client-app/internal_packages/unsubscribe/README.md +++ b/packages/client-app/internal_packages/unsubscribe/README.md @@ -1,6 +1,6 @@ -![Unsubscribe: unsubscribe without leaving N1](plugin.png) +![Unsubscribe: unsubscribe without leaving Nylas Mail](plugin.png) -Quickly unsubscribe from emails without leaving N1. The unsubscribe plugin parses the `list-unsubscribe` header and the email body to look for the best way to unsubscribe. If an unsubscribe email address can be found, the plugin will send one in the background on your behalf. If only a browser link is found, either a mini N1 browser window will open or for certain cases, you will be redirected to your default browser. +Quickly unsubscribe from emails without leaving Nylas Mail. The unsubscribe plugin parses the `list-unsubscribe` header and the email body to look for the best way to unsubscribe. If an unsubscribe email address can be found, the plugin will send one in the background on your behalf. If only a browser link is found, either a mini Nylas Mail browser window will open or you will be redirected to your default browser based on your preferences and certain exceptions. ## Keyboard Shortcuts diff --git a/packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store.es6 b/packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store.es6 index d09009d21..66f0f8f67 100755 --- a/packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store.es6 +++ b/packages/client-app/internal_packages/unsubscribe/lib/thread-unsubscribe-store.es6 @@ -3,6 +3,7 @@ import { TaskFactory, FocusedPerspectiveStore, NylasAPI, + NylasAPIRequest, } from 'nylas-exports'; import NylasStore from 'nylas-store'; import {MailParser} from 'mailparser'; @@ -95,22 +96,26 @@ export default class ThreadUnsubscribeStore extends NylasStore { // instead of all messages based on the assumption that the first email will have // an unsubscribe link iff you can unsubscribe from that thread. const messagePath = `/messages/${this.messages[0].id}`; - NylasAPI.makeRequest({ - path: messagePath, - accountId: this.thread.accountId, - headers: {Accept: "message/rfc822"}, - json: false, - success: (rawEmail) => { - const mailparser = new MailParser(); - mailparser.on('end', (parsedEmail) => { - callback(null, parsedEmail); - }); - mailparser.write(rawEmail); - mailparser.end(); - }, - error: (error) => { - callback(error); + new NylasAPIRequest({ + api: NylasAPI, + options: { + accountId: this.thread.accountId, + path: messagePath, + headers: {Accept: "message/rfc822"}, + json: false, }, + }) + .run() + .then((rawEmail) => { + const mailparser = new MailParser(); + mailparser.on('end', (parsedEmail) => { + callback(null, parsedEmail); + }); + mailparser.write(rawEmail); + mailparser.end(); + }) + .catch((err) => { + callback(err) }); } } else { @@ -155,15 +160,18 @@ export default class ThreadUnsubscribeStore extends NylasStore { if ((!this.isForwarded && !this.settings.confirmForEmail) || userConfirm(this.confirmText, `An email will be sent to:\n${shortenEmail(emailAddress)}`)) { logIfDebug(`Sending an email to: ${emailAddress}`); - NylasAPI.makeRequest({ - path: '/send', - method: 'POST', - accountId: this.thread.accountId, - body: interpretEmail(emailAddress), - success: () => {}, - error: (error) => { - NylasEnv.reportError(error, this); + new NylasAPIRequest({ + api: NylasAPI, + options: { + accountId: this.thread.accountId, + path: '/send', + method: 'POST', + body: interpretEmail(emailAddress), }, + }) + .run() + .catch((err) => { + NylasEnv.reportError(err, this) }); // Send the callback now so that emails are moved immediately // instead of waiting for the email to be sent. diff --git a/packages/client-app/internal_packages/unsubscribe/package.json b/packages/client-app/internal_packages/unsubscribe/package.json index a7a9b253b..88f91dad5 100755 --- a/packages/client-app/internal_packages/unsubscribe/package.json +++ b/packages/client-app/internal_packages/unsubscribe/package.json @@ -2,14 +2,14 @@ "name": "unsubscribe", "version": "2.0.0", "main": "./lib/main", - "description": "Unsubscribe without leaving N1.", + "description": "Unsubscribe without leaving Nylas Mail.", "license": "GPL-3.0", "title": "Unsubscribe", "icon": "./icon.png", "isOptional": true, "repository": { "type": "git", - "url": "https://github.com/nylas/N1" + "url": "" }, "engines": { "nylas": "*" diff --git a/packages/client-app/internal_packages/unsubscribe/plugin.png b/packages/client-app/internal_packages/unsubscribe/plugin.png index 5faffe6b7f6af359813b6df13f3889f54f476ad6..7f619691d04862aae19b26824f03eafb559b6de4 100755 GIT binary patch literal 29025 zcmZ^~1yEdF)-{YY!9(Nj?iPZ(OK{gfkN^RKy9a0>xCeKK;BLX)-QC^&>&*YpGnJXV zRTrv@uERZN>)Ly-6RapNiHv}U009AkEG;Fb3;_WU1Ak6~djtN>YqRPK0f7K-E-I=h zEh20WLMk{Q9#%C*1Hbq5(Ue)8($ID}YX9nLcbOI=2tmR5 zCYccS5)zmmIdtw+9R-hs5a00u3NFKkgazgok}2Ba!sH|}$@T8bs5YKxV^m{t!_Ia3 z>FekQN`#aV6of08oLMDzKisM094BK^OAk66qFrPrP+#-Y40hnSB|+^7nSq-}ixuh& z1cZVq3l{?f$U!VY+N2UlY((;l2Y!7V95xKt4@LcL5oiNEf8R(>sD19*ZYd|i90U=5*~P7FYR2m=kI zj4xYei=u!kAWm3K5&DXM3SKYZA=7XV@*VuJaCs&Q3j$TA-%pAXfMut{9G+8v=lU=U zqWm}ZHG(@5T?CCzv$gkkbRPIb0S#w}E~qey6d1^qp%Y@`O0_g7sw{M9-NMHr+nF+o z(*>rg*hMIg*xlm8*(=!S<;{E^lXD<*!)}Do3oMhY%XA-i9*^0BxiUk7 zA@^14O*Bej^~J%WLXHWg?U*vsW}RitPBb4v!wStcjH~F;r2YbY|E39A$A{n7s>A71 zP=(5zIKf-$5S8AfO}?*4x@=6?&IHbHoMAZql6zV@W6maA_?w{xaMFE7dlJ_0&lAqc z?{J?Gd?PZXSSVe9zu*_)1HR#jV6VS5{P9y{i<%C7IJmV7XM@Oywj#+Tl}p$|lq_mX zii(0+`5kSjstk{0qx27o7HY)E>Au=6pdG?JNkjP32QMKn(M-iy8ui$ZGHlx|l^25x&?NT!PYDCTca7MIwV*`H*v%=ea=>ZU+6wncPv&z(J z*DBv?+bZrw*T&Qa>&@p4=}qn}_*w!XFC^WrPohgAxmMlI;Y&*wLZ?uZ%U0-K$T4*| zWiDKjQJGQo@%zWtHLVWe4j58MQfN}|OovRnOj!|KypTLG`@HUP1oK_DqJPc& zLj48%Ejd8)TY`9(c!?O9*oBz3n1r|hXaKYj+7m*AWrgj@5QwFMeu*ZF&P(g0_eEb< zaY-(PHjUa#|0xr|kV&=9SRuMm-R0Ajl@ptjO`&s9zs1q-O8X-=PW8KL#gs`Qw|P-@ zfJ3!I#TDlME}ID344W-mE?Wy5VkKIod?jtATBUy_z1@JFm)*P_qg}*y@P)&@)VKt#tZ(O_AgGYuv+x_dM?jlGT$9CrHhN6j&I9Q>fn&Z&1pR^_Ps>_V@Dkft`^{ zkrl%O$&;M7HmHkeb=wo_E2ZB{u|-%jAv41=iE)X(Tl5$u+G~o>K~2WHe!nMMqHE^z zVEVMJRSl!(B8yIH>fjF54=SP$x@+}z7BLw)!_tKPetqe?LLo8(oU}28ScTh# zrxQ<;OgWeN)Hx_$G#0%+KFS4(_Biv7@h0-Rv6-;n8q1$luV~dEE@0Lco7Fv?q%2Qr zg=<~AgWQd7pJGd6^kSc#Y}!}K2>Me>QVMMd+RO*G`?t5kPuUkW8i-p2-CoxqpP_qE zJVp>lo8ro245D8ve6+qE>MYyHw(0TXxPJXPR&cgOdX)K1^ivQc$}ILdwh6`uLR-NJ zbq19bji;Nvne1oEHUUWOty^`hmaMR(PA}np$7w)f2+e??HqHV;yr*5sgP|qTlC?SHX z)yg`T3mLV?R*1(+$4lWE;p_4VBWX-kWi!MzUL{R5?iEkbW4XTuy9T)vG|G*2wT?`k zM-5E$QV-@AF88$8YTR4&Tl{DB%2%7$ziw)$JFdnh?{G5TB;Po%WUX4XSvfRWwSUdH zrtVDFh7EhOc!IOKkHdz0fVaZp;o4=lb)eVO#CgKK+Qi>z>)AlDLLeDI@{ zKVMioUWZXY)H6W{*s5!2$d{CP6$uA= zLI^o;yrv!-G^fGNB828_sWe+o32H{dyr{K7r|-As{ZyS52V+C{uTom}5D-|DzkeX5 zl_}03AcP>K#e`K|AdgdFKVqo8^m>285D`Ic0YFKee#qez2GY+7@w@YmUY_tR?yD&% zoIWj%Tw;v6(WUv3(IL>a+^&eCPy#LBNCRFUTZi$fl9z{1Ok+|%vm8o-2Pv;E|sAQCnhc~?ch+YTBs~;^y$;}QaZHSz{rTeDZQb* ze7Lc(G2G6(zia}$t*>mpiHSIcdQG(-PX;{@$fy<4FyvSY7~tXI(TIu56EfS!{{B*u z6u_8248L||WhDhWy9#qQ-*mCYY)oCHE2h|ykyIES2L&x{zYdYE!e7J*7O){TgzeT` z#V5OsE_l889~_o4Mn+k^cCHSWLbo`ZxXNu_o*|?}l50|G~eC2Gb7$CJMp!hnDnTt&kV&dro+|RDX38;BQ9(O%BOK|IJb6;Kdfb#Rlxa zW}d?1D5K!&>KYvvhe<2$?7+RbxtVLXJ)m5w&B5Q@)y37=%s}uL+W^Rt7y+U#cSjMw zMf$^{4D`oP=gOz@OcW@Q7pfLUi%Ck#arp5om{b~ATbKFROGpHMnXeQt(kN#_#(M{Z zBVUsv|KE-KUWky8#RA?H%s#53y1*xA{+uAdgT;TRTrJwN#EU+qs;nom-h zFV$C2P*N&k*iOwG8UC-k$%wR{vxBqG^opVRp&Nqg(*qPVo=GW?XL#-Fh;u$^A3t)3X-1D$%K zJpUWtK%ZbxUA%Jg^JP_4V^7FL6(T1t0Ue%-1gm);k_Q^>cO7OaW8!a7{vuZ~I!H+b zvd>@5%*+OTpz5--G!`n4rRjNmDqwC(@ZIs{}d0vS+rOwFGRR3%0N zBIDx35W9mQ{U0fVjG@9Y#Kt(FMGwh*==eo`?V@f-e=kxm{UN}~CHXgp0((<9y4V<8 z5RP)WKL7BP3)xqq6&y0B7cTGuQ@tGhCkD>{If_s><(j52IGjnR$5rBp!@zFXJ`vaC zIUO&6ed&bVpM(0pcIIm*+-~a!7q}okHnO+(8F|iy^y>)$3hMW#nB?R^QkTJQa-X>W z&I!ID((SoCTm>gU0bu$smoHoepBZEzAwg&Ns2JO9~CzyikR|9qE?bG5;YBF*L|tc(N!!gbA{s z@4Wp^pZlqI0b+DyB1w7MgG_tC!zKHujD+ua`qY9eE~x zhMCpZIuH4In9@z@n*pB@I@HCv`tycU)K7=L{=afLFbY6G4;mBgnkQmIb*-ryqW}Va z=Raxl6+RGu1L7ZN1!oy}F6%ix=)o0!{|(S(7pi?4*MF-Tta)E43b1*6BLiKE0h^>S zgRyxB2_SrB%F47Mk2-P!A?9(>QvL|WKH2bG>c9%lR@!hb1p?bEHNwDO+dDh)cLnt$ zqEQOLh*@l)kc+3!ef|CL;y2L=3Do!Z_oV&wu|tZ2DM8Vi=2fEeiamz+UDBjT&e_`)$~o0}$`Mj1nB0z(ugy?TFO7{1A4IH7Wl zg_`+7PVm*~tVWN%dzhFcwzs?0QneP9LK0b%({VgBI3|J}{kQ$&z5h%i8iW)-C=nhB zHp0WXn*fxT$0!2T$99P@0@_p_$7&m<%BPFs^8Kd@!>13NGBG`2p*gJdN4;HRJ?!3h zO4If+DFU9_;E1)IrCz#~6{_8@rlCuEeK^bBz?I2wuvpA^2l^* zzr;0M?)1l(E~>WF^>b6MypxrW$6{2T;+R!<(4Xj~*iQL(Ud(_3vK;#f6^A&pfYF9e zsL(lMElX5Z5Xe4g3HfFnKTo!>D@feate~f|!r=LWH0fdb-TiFa>bv4A0;7(+;pFS9 z$piG9h4#-V%?WlARbe9xWvUE}@<6F1^Zl!FF~YYTqQ z>~FyawCf+wGK5X-qwc*ZefX{)1^ZT79z(wP!+nGA{p>j|e(_{KDpO+-EIyHhS#WAU z+NMZRzG+dvwRtGt*XVd?@^E#!wFAGo9e7wyPxiAueK3glA%O4o*Q&|N6U+{9LDua0 z2Z#3BFPU4j(n=%U@rcb&CK+p#dp&WNMe@y; zDpqH#>FqmNcK;1N&4PLan-TQgw{yvs723}Nyr0r314&R^;;L0wkk6Rr+PvGI-dWa; zAR<5Kzn)3DK2K}pTI-$aqxjBb)?ZcFR$MF`zE*Yt9iYuunv+z+%8T&V%tq6uwT#oa z$w&DfIk$78s5m3q3Z-g+3SPHY#Kx-v2{=%v(WL&c(wh=t)j^`*n0MipSdRYyj71$hadK317ZQ!QmT*nIQ=Q2@bLf_97pIM)4&bnE0LE`$D>YN)*cZob3#xBi2 zviiE#DPjbYe)rScyJL^7L$hFReGWK6?6*52hhnuwg$!%yH*8@5!|!e9S#?|A3Bi@A&JjugIVKp)O7f0QMgVA4JWgOk&yTcZ7? z!kD6@qronKMkIqAYIp5-5FT{ zhi8%)`b6cgmumE_@P1M99*=@^x_v-{?m5OHd_(|=v*mnNfUXsK*!#kIx|5rou3)=7 zA&)|>s=Oyz!Y22+vWJKUX`Ln~M%RP>-dvU5w{DmR5W;y}qH;Jc(eJ*@DOyYyGcg|f$UUr@sn67{@Ch3joFP>#X81yHjjz7+XkXuN(ejjq)c7I(1MyKs z+d=p=EC3Wam%8?ELKlf=D*-6BiEA~XcNRC?@x#WefhJYN7cBQlPs8V5zqoUsB}+hU z$3gIm4ICz!w8(@(;B9fPxcJXLp(;8aH#)jKuK1Oa-E_Hssd)Fj(q`2DE{al=}Hf&Rdc}DBr!R{eiymn@G6u?l{2W$L!vOsK<*Y*!TiU&1{Sx$ zD00aw=#>{W;%vXCyBJG_u5O&>2h!N}IPF3WQj@g#l@ z?l&il6rgHFWLFj+PXX7;tE2H{1oa{ftf!cz>cWo~#*1|}b?W4%eTjpTI&J)nB=tve z8s94(Cerv^l}U_TE7v=NT($K!z;dY*56k*=G+`(j%8yOR>oDdAchljT5%urFOzaJ0 zwe!csWOxzSE|eis3>?y~*6+8n9`D#slYsAsDhs*4y&?b6&I=&cS#z}P0>0Bf9_;G` zQ8)?1+y@jP`|xB5B)_+s=>4_lc{WuOF=aL|>biy6?&t)rdH5^0^snU?ic%4|)(g$lH*;kSw-!|VB{;JdN7TrPhh-!eL?pVWT+PKOKA3#HEGX_XH1Y|r?j zNUI))RuiJZWXB7&(~beV&>OyYY)H~yN?fZGCa|xf(0&R~ias&k@286?PasCGJyGmVd zSx8@KK%_7w2DApTKy?7f;8xPV%E3`^g`-OUL^idFN#gTM%1$d7rNd+|3viqLh9g36 z03i9&k&KTn@V!j8LAl1Uao=(7RIVY&1s6*d61j!6WLrb(&r6^8@X>0*jDiNifS?F!)_b7nkVwFUqv*pwt#C=`_{L^P zxFR|p+0B>eY~}7+A;>366F65GyJ|x2vYz66G{<^G?7<)9R6=5;K{_1P+h8w-rhu)& zHPa#5fzw)KM!-uY4O2lg^suo5YZWF*bJC656%vit=vi&PtSylCPCC9^vyfl>$W^4m zpxL-E4Ty7f-^P#swdLsE5ZC+ciQ`goH2un{qGtuv+uFAq+)ES(X@R3N1-$`s$Lk`z zKhICUdiS**f)HmqZFhgNEc1Jmfk&LnkccS`8Rrxhf|Cnv#p2IQ(dp3OS7sq_FRku$ z#N?k6E(leq=}q7*89Od3fDE+10u>SYrpVH<;2Y2xsSn$B>FlkCT#ICpD)~;Jeu6!Oqp~2#AquQVuk-5&klcW_sTK-@zsbu#3I4_jR2sAV`I2 z18*A9xsEHN5f}W5wH~o9t54mIt1SB>tZjQ)>K8%z=@TO276XZIr>r17QtAZc=LE6cq<(V%m zH?2f`5bI(6OEa;0xfVSf(|$Q=%d&P|Yu`(iT>N=2%my6Qr?VgJG~}!Dukz*E*#oYM z&$c38P(KB~KTXWW#omxiJifX2^@lwceAZrR^Y*UrgKMPC&2RF{Bbzj(>j`2O6`TS0 zr4IUY{7Ehr1YaplK`Z;KqcjwtcUE?!BfYK92b5hXi}aFsbOYfLRCTD9m% zS=gw!=(L~m=~pQXDtTbRslo0#WflMxj`Z_m&Xf)1=<-7)g?hspJfS9|pF)^(9@W7z zA~Ejy_!#9}{YqgZ{ff>9e8#bCp^v_>GPdV;P{RrPsR|I#1Ox&ea~EuO%E9~*;`=^m z2e1KjlCJ5ZNb`=%EtQAy27CK=vw{{6^5u2VOsIN*?>BxBsXYRZNA?{BWG^@mrmc@J zkLt<**cw>Dn)lznLhd>q)>_SMF_u$Ob(L-S#zcj@llXr0Q>7a3xu@)33#YmDjP+F&Z2G`L!v0{=_ z$arS1y#T3IXWim?OEw5=aD^D*l_<)Qb@?jM44_v~A6M}Pf9>Kq8_qL8Zo%s;gsRawO0h^Zy;OH*i{)Q7= zh?hMBBe?IOs?T~JN0}G$V$_eo~PyEV>( z`!HonTr!7T+x)A^)Jw){s9|T`FNesUom%w#3__V+ul^|0Ulp+>F6v#MTu^95n-Gwf zsnZ`?_|Dcu-4^njS(>#(MEs`ItxbA1mNxX}U{Jqr88ySpxv|5>Fz0!hcs=m$DRmw6)zuKV3Jp?ZYoefBr|l zFQ|8>)7aW@NoC(6n+Ld=&P78>D`WslDr)S)aKUPe{^(-5Mj$k`4K*S)mToDB6ucXC zcrqo{IFrx4Q5T^~5f2)B%JMKuIjt9R5~4F8vNS-H5MI3$zSM(q8CezcCn$OTR}3+z zW}y6V3VrV@Cu4g{2$f*@26s+44s%kd2F7w92PEp=e0Gp7k4It+ip0By(_NH-9Y&oJ z#~T;MniJ6^OyqfL{`Nh&)Z)^gL+7iQX ze%w@zQYWXgxr_-}HZWkz47@cVbU)^J5buh8RPc6{m?>pGxQDbo9j>FYup!6^$iOIb zORlv0H~x(hS!-!{jlbP_)90cHP!ClQ4D2WP_6CEx$O=YmY9vVC=-_A2c+tQZc@LR+Z@xRgX<~X+GFt!T( z=%U@#D5S-rJc7V+F+`p2WkE=og%T)HrSs@yWir+d89#Qm|0;@r%lJ)7{33ol>#-k9lx|hM`Q#pVVVeX6x7a_W(b_i(fTgZ&RK7 z*hdBOs{#wIl2-+aM#K%wv%6RUDDo=L?qD|+lu$*FkgtI>hE?`C(H{yOd=GGoL7R*riV6>X1yqQE6=Fm#zOkyk*oA9D^d6W%h9 z@XknbIrSH3PF)S0iKPE1BiRQ_)JYgAIR5i?X(kNnv=t?Sh?Fl5T9Jgn%B-PVo>wq|pjjt8>W zDT$RcHfCqsVk;=#o?2Fy9g|C$e|%!~N%3aoT89vKA>D2#y+3+NsjjcVQwB+Cw7W|f zTedX0Tm!c4g6{T zU7HYCK4Ykwo8!fPK?7H<-St-H7dXH3!J;plHq9OMma&k#Ti{0aoEfgNvhr44+kFk+ zjm{~V#I?or6-#%-(}RY1vy$BXn)szX<=2+`oH~ot?t)$Nn`bLhz zY>Pw9;Qq+P>Fg_Qec69fNbB$U!Nsx+l5o4KLyRys7U7_%s}Rj;WWfLvGu&zepkA%z zQ546QCQCAw7Dp}5U;t>IHbvGxG$6n&k>2sGJ&`IN#NTc)p8%4i@Erpdvx&wd`^IhPxku9g%|*IVSgOTF_GE3AiI zxf$elm2om~PNz2oUDV1Rt?F2OsKTYd!U)cGO2sbCo-I-f$|vcNuIenJw3< zlHhSV+S{WUcai#3uu%PMzQ7K(0XcOn0i#qUYL6JlhwTu+RS?+CpCb{{F?Z^yW-#1% zeQ=;8F=qA4fH$vk;Ydl3dg5(PAy87g?%4yInIxjV*eavZ}A=?imV_gfef-=3&a@$deV!2{quns#Jeynw^c?pfY0ef#RkGkyPC*)Eq( zJ|1n?*#h`eM;3!8Io|T7gP9{^-rNPNpLa#)jn?u^mK1ST+XHciR)TqXjS@#)KPQ~* zza-%1hmg`}IQY9wY#iRI@p;M?N~pE&-21^ubU~U?K~dj5HDvWn!bl ziE8v0zLQYcpvTV6Pa?$h=Rs(q^@a!mqyk8O>qd5!0e-24#A(>bs$I@<|4cD`+u=y8 z`|@Q4#>hZ#twYM#fTF5Pz%E2u4i)BSm(?Enwn1Joc=CpOw#w&35V$q>hI~X-g{TQ` zCL+SgWwz&$P{3`S5GDp4nHYIeRpT%xhl23uiU#*Ob^VB`z*8?Fi&1{FB? z`kZEcNwr`zYK%`N9DliNF3%H7X_UO0(%8OcK@6}Os3 zQX;3;Mae^&gcAMw`n;TvZZQ#)J2w}0f3gWuiS=?2AOi)F&oLjsEI?TB8EM%{_s^!BG5 z?{wK5(M2b_!8`a$%`iDBa!BCU5)w4{ETP;xx`~U&h@1tMTmm{ZZu<_ldB^)v1|>jt z{}GN?wlR}lu6WG1&?ealy-og*_cw#%<{Lrz7juJy|0%kESKnZMjLJN<$;=FH*;*lv zk_40?5fUM{?ZlB&o^RsiDmPO^2h;LFQxo_31H$KNB(A!JPW%boN# zN)Acn*#xDTJgdr<(`hJHW7%HA=-j}A05$xt6;rL75{JU;`pl_)HxZ9c`OmeOaiRbC z(C-gxpP>vG(kZy3OM_;njilZMPBSi(8Mt_B^j7eR#rk9z1z$;>s5HVdcQ2u{9OQ-g zeilQWx)jmtJfy9(>qfZmR8g=zjY9>46JoQ`=mx}{!7b*t$a(N|jG)G2xP~q~yYkiR zEK}}bD@K{3yM)|Vh*t28pCkkds%FkmjG&v^!OH`Y-VOn#gX1SVn|^7*B5w`+nNduk zX-Q89kwrmpWmj6DOYz6pToPTg$vZb3)6a#}?X%wYveinRY}MM$3EKj1PP=H1#sFom z>zwj1e#cT6&PKI0J8|=CE0fMHlipU%tU-e5a5A=$uci}o^BoFqfyBAL=hNyd)`In` z64q?cvy1Lq6v*B;YK|JXo!9QC{%tXzh~;lwoan?g;1TmU5bMqA)9mU2i$HiF8<^Qa776%oVVDWO?mNmG5Hm! z(}fv2wy5hi1=cqXe9Xb61Uc9&ELt8&&G}ff!&%#O0jV96v}%+C=oH_(^Z^O4rqLDP z2ooZ3$?bQCq8O9w_LPYD!_q!WjGV{9&c+e{wu_X&dSw%rl6rA@_2|nNED*65oVW#MIb>IAJa0yE;~53Z?cCIamW%yg;nRvaZH*rjMSvt;D?|jqbE;j*dAuTP92@Ea@^ly(=U-Bf!X=8l^LnwuWb2P=u z032nwjNnROkHc}M=o)RcB}P?w^DA|sCMm1M=N0}sKAL;85vd2n*XSHrFDkW#nwv&J z&i|sjd`oK|;2%`w#N`kx!4e(FEB@}zSaQNPAe*DN$#jxTe!|H|2X4Taz^FRPz_?u< zP&PTA#+%b+STNV{oje@!IfecD*-D)^Yfpzf>n zdb#2*?zCFzTE+J?#tgH6RQqLLx#OEqx%X=ucCNwei<|vrEJhNiS=mm#Lw_`xU+>na zz-$_WlrCkNOw@5GHd8crm8tACxjQdb24S_TABj#sO7g zepT(EM2fg#%Ayl?Zo92%XA1j%8OhkVfIqkxz9AwRY>j<1tbj`zOx~Olxn2|{SpV5? z+oW0814V#bX95?0oKxTw${@=osj{2oP3mQ-V3Qhf6VM4Ics}=u?WckFednaYVC*RM z;Le9+2M^R$Zr!8Y_*6OnJ~IB)5hQ~&yqH4zAQ8zF*q>SuuSC+pWIdVZTOQb@|NoBdrn!$7-0=u z%D~uEq7AaF#sN)47*?^O9yJbna;I=EaK^F?!GTI7ZQXEUApygyS|wZ!J-N2K>gPsig&2nXA~ce>0gBs5^zY)$E6>NFh-@Fn2+t`jA| z>Gig4Wo(6Zyr{Q5KSnTtzPwQeJfWkUF4BlG> z&V8@KK;eE>iJ4Vg{BZ8I1;&0uhR5h695Nht4XsNa#=%x3QUNl*q8}*reG9Dw8=^2NdbdRUTTR5K1F*!; z8YlIK^4q@S9}w~SXz1x>u?kO^6!_0`kd&9zYpv%uI9@G#!{a2vLVJ7(SjI3VNI5ua z###*&lJmSH2sua4jE~?Crb@}{R$cS;ub1nv7yKoLd|(I9H+xI>?(-0;s>{a@iTMWlV3FiQrSIjT}!TveyN63Vda zfp8u1b9o}X8tXB3zG|^eo7csbibB7cN?zYW82;AcXKzG`YMBMdr>k_O%i7jd7B>b}m-u5K<44*eJIc@GI9 zU8l{&Lio}suh_8llMy`0`n)G70SFh zEmWs?0r*B)pRSy~;~0M#UEx9nF2g@8|rIhl#Y{q`hIkJniS zpMwXPPqxwFm=4T3uC(oxpnrjrsPIi<;(UO8g-`sgKxz=F6DmbPG9Rac{HSt=&BR*^ zC5k*RJ@c1i*yy>s1T4488S7|r<`%}?xWjnX{HdmTyTprsI#mCFqjjpts3=l)v!N;U z#-6)M_tQ25L?o#yw{5xzX=wQNWMlk_oxO3SheI&_ zc7Uz)gRWh$KBse8G5v6~Un03bLKj9$)GI))y}}RFmWGg;BXo zIbO*ZkJ|geLE(Cl9L=SvHzt!iveK#&-uy&NUp!H!P;gO)Fa-0@sOMj(lf}1(<40hP zLnEQ#rTo03v83i8dWe7aAS{w2y9&((qcl-cQj*;(|LvZ6_r0m#-?Z9 zwHdiz{!E#k4)t=gdG@T{d#k0Ky6z&9(ho5)r4ArSC}u3AMR)K#%(7tFt9FhALbX?+559InyzUd(+U$Xa~itT)Q`?;*K&zMn*(u~t;GD|8JudZo6 zwk~&}z_5{dv%wSlAw6l6%acg)IVtfE#PLgvMBqKCoTPeC&F!R87Mz!~ zt@@9d`Zj#BC1Sd8|1zape0tqBWF>o#OWs7+o5tbj8oSgL%zKWm;3~jD!wbpM}Ed@#2i8R@IpEy6mV#?6r6N#P#DKKH=S&)naH%=trP=Ze99b@1Ji~% z)*(y=re(uU8cy}KTHNA>p1cCVr2~2rn`>oG^=DErX*C+%LTXX3$vG5N8XV~9U(@d5 zKfbv`W(QMNP6975NC5gRtnJh}*EPQ3}g1Uda z932clE@M)AhQ+|N7_-{BeD%zm6w=(!4}4pT4^?5kP_Gomvw0EAy2!?^aCm)}x{kF; zp$8M+Ex;06k(Klb%u6{ARvd6x`3)QF%iL&oE!!F%6rM!zUN+73wmlqCt&h1>M;NY_ zPfM3B47>lxjU?XyZXAcjO{EDnL7;s`=uC*gGFQs^IMjQC^$(jwS#Spd+zd-uaN(~# z$uZCJ-?POeUXskIvquorxt^hg$+BrGf8Kc(Nz> zlPF5-4F#n1g4=2NRpyx(WnXca7OrK4!SqNKuD1qTiI2o?+TosDS{C048K)(Y=qg(% z=;>w)Db*gYqiHZzVVyR-4F*@-iKhpZY%3T_|?T6f(NAP_ZKhiHKIfRipJkrri z@3dSMROxFr=h=ItICbj2MDbmtHizL|V3*KU3P&QCJ+g94Q;IDF3H01&1cA~uw(sq^ zqw{q;pVBHvFp}+8qCQ1)yH{+PHBQXbdwqZRc;{G%p{I3GHQJxHNF4v&nHn=01^vG& z1Q+VD1|(HCnF@4enQr%zx3=!E`f#R}hd>#|Ra>oEyeheKB?Kc#; z8*6q6xN%43O*U6vg03H-OpQ`+-r~`mjnUAv0=9!SvS%Ik7t}}~)Erp57Vm9;xq%71 z9m4=ejuddT-)~ zmi3}RCPjHoi+4#gEw5Q&A9ZDID?N`v+9l~rV$>}Boy4ds5=a~}A0<=>hLb@cC9Fw1=z6*i*r1a1L}h z%NO-_lYYzpXi;%b;#GcnWw=Wz?B#zF9H~HVEmNiC-S-eb4&XC6aK-yn} z$;zC%FP1~M!iq-+5R?Le2bcf;hJ`3VA}n zvt{+NHhD*C8=z6Wah0$Ve^km_jTVN!Q>d>QWXRDB5EG(qoI* zW*|++oA&;Ibc->)Qnwtj!~0KP7lHe3;awx95i&{4G|cO2jU z1vfIko76JM2Gdp`p7KoPlKV974XbVXDI~p>RYwH#Yu!vyLCM)BkpnBYW zS6)8L&dPQmh$>lkK^TDEH24jIt_qI#w|JZs;GLsLl)WUu z#R6@WV9Xp9@^t~L6z=YTeAC6obsKkm;LxYA+X zh&RAdHYP0E(HleaXL1sxQSr& zGwLY;MBwB`Sth<~`_L$JYa{F6`_sz2JZ*mpfBW-CapR%QV(o{Gjg4v&D5b6#9HRp~ z-vsDTUEkl=30OH*T@!mbEXjuR zvS}ev8c-{(zsjvyj!m%tb35;#;8}z1%*qW0K(WOX3c+MNWuQ`g_rAkV&0-E8r~S&< z>FO=E=LYO2V?*EF(9T04jF?kN4zwJioq( z{+nR=uhJYXK5sfblO~@Vr&6LItA3}2a&I8$CO#%cRRjGBYTuTiFe*@ zUFV8+zd4F}dU_&TAw4ky6=rYJwL?V-vHrdRf}wH(S|UhT(p27&pFt5;T{|<-k6RKA z%JdU6_SF3Rr$ii}pp^p$4T4&z65cn-WR3R5h17wtkg8ScFOchy+bkVZgTtcldA*`% z&0acD)5y+{q(6L!o6J{`jiXaz5bio5_2WsRohXNlZ`(ivU!m*S6{uB$Hm@QoF|6*54-9A<5LQ0!et;1PaoSb042&|AJp&;%ii@^cDa}&RDT6gW{Cru z5n8%xtj3o+!|^yq*kVB5u4P^dAl2OMQiHwk(XZ-lpWj5L7Iemi z-~hT)6A^|eb^83lk(XJSlXG;tr^&+YmVpxDKkmP9rTL&rl*Qvy@?U0@2>ev7HT@EO z)XcygV=wX6_=K^bGXTfOS5*d)et>&vsG=N83L$Va0HSJlj;Y~wS!XNa(<>9Lqt2UX z&)`X;cev>66aoURkt$9ny_^c? z+a|sGr+iw0eUA0l{6bVQLe42}$GZ`^n-G15ly8Z-$!?x{rI(CM0k(}lSPOl;4h{`pAdu&? z_H%AsUwe`KSa>&CC&1HYXGwW0vvqIM+OfHfZL(0i%+sy755MOiqGSa~vW_nezr~j1 z2HfBA*GL_1jAMBF_jn(gYwrH4cG$uO|FVd@Nqy_!c0$7Q&YL>_bY=2+tHlnypKCybC&^qK6 z5e4&8bYqa_bXaKPjfCTa6x06ROo?tvQD?Wq>S^z|I&`t>c_7%2;M`?=!qSGB zp;dMwngPy2Y;+9|vDE3XrDii~n?z}iB}`6CTzy>#WI_RnWZu(o=17L;fLcdAiFvS7 zTSKFKE>;mN3|oh8LGE?f^wF#ueRR@Q${B5qqttE;I*95*o~bb4X1Sw6q>l8?bJhT5 z-CemGS`Yf9P@F?QUkrVu*Iqd0rJARjk2%{0o>N6u=JkCI)vUv6#XP@bohxz>zrDT} z$n-9lJQ)l(3faUYUadCX=%icENkFmR{Z zHDSAGDp)zIGN?gKL`0;@#n3WTrwFKcA69`!eXaqFZo**V?60opby!{9alCq&P6V zg;>a~v(C>h+?uyD)r~^6&sz3*!uKnB0F964-tJ!f6v0@uW^$uoMW76dW{HzumnWc=1rEpxS2G}gvGj0rwGjvrZlWBk_lnzKWu5l@#J zNVbs)Hku(iej~W`l>B?X>pj=J7z%4-nwOlQp9!}$F&Dx-X%+2!$?Y*&ZWv@8QejlQ zn4Ly>I8h$f=tKf?v5092k>^uRQP{gGkWt_cjaDRZnmTg_7=lQd%w}+KxOcC-003%a z1Y-}fBdi-&WG;O0sR&ctisE_v7zjX*4ehp{CI}z zA6w8#R~qMqXdLt>#HFH(&_j}vRtI{OCk%MDt#@)Oi2GCa_k9}`8gy;Gk~*Om)CLrz zuhD?6p;!)yJB7aJ%JlR$aSMu$5rOB})|2NkK)v4OMK~breY zU~atTuqJT)zh4Vgg)o0jYJS|N^>)&8#+qmfar5k^urB|^kc6*a)v3AwKW zU`V>X$Q%gzf*Xf#(WyoBtBwnR8Mj@dII$Nw`LU<+^Xpg`*+&+ikAjOrqLP6`qLPl0 zIMMd$YND$%R);pbOLt~@Z2Br{ONBb?3@jAh8p;Cax`>>ae7h}^2y?Y~(lZo}x0*5+ zJ_pua8IE(Rfj?8P`I=TXF98&b{I`DIcKxOr_~ZNAx=d67)Hr|bgJ)yiqq$>ZmThv& z_&UF>MdHVwD7;}a{uI^wK+(E)X#DG+Y#BHz;vyr#vEj%*iC7so2A?YkL9N^)!3;fn z$F z`;D#}Ji)pcz*}{+%hOJqS-K!(T3lXbFNX!QmYSNe>yhU5Y(<1;j{7ano;&4ND zSo^@ckug-p{IlB)%X+`tB0A$$W$(HI4>~`LwKu-aePkX`J;E(YFcOdEARLI2qXj zG9m)*y5|7zv}p3E-JB0psdbp6G`al(5I%nXo@*b+>9%zqxaS)v6R=WpHZN%1qogi#JrUS)V@81m#*q|1;GDzh^0FmfYU==SXf$*ZCED{H)O|Tf-LS zk=*@JIp8mr8kThuZ6)b@EHvfvsBEjL@yuZ%o>qq3%EP8R?e=qB-Xz=-!+EtJBgTuo zne1K@=>?z^wl=~gz*M*-+H_{s-%N@06txbOzAxC>-rn`q zFl}YQ=67?TMQ$m~V(YyuG|%Ph;qs3m_i9>;y|v-SD!)Ctjc25i^U&2W&mudQedDpG zwn!hLi-{Gto6B;p6HTwjHZ7L9D@6SYhP@1|1vZD&g|*UDN$FR4Exkuxj5Zp4cP0^O zGx(&PCXjM*1~3G9>IWB7Ik|PnU~7I#iDvy{4>~SXT0%lkq1*U_#oO!)gy%ftuiot=T%@zb z_@$Uv*Z%4Jsu$kokJi;DOlWk|WzFxpqRZi1w{EE(`h^=`)5OqT1*cayXn90O#u2*_ z-4SWfvE(|=gf!ctv$@$PT~A<<2v#ioumiC>1@Q; z)FYxayklw_CuuNj6k}|DgnfGN$kdifzqHn2mdx%;#5 zK1X{D14UXAL$3OBp$Vbv%Z=*F&k$6c&< zDiNA#!6TN-%|^DM;vgXvYI~yZ6w9`DYlX)osQVGfk_z6PouD0T#e7{74D@%ion1n_{0T2a2zk9@ zz_CLQEmg>LURYT8XzxSyHR8LZO`;=yQSL3Cr>3h2sjamAjbc#6=3#G;FBREilOcTT z>nipvelbc85gF5`ai>eEBv>Rdoi+UDK{ESgv)|c#vVz8EYQDtTJIz%v;uJ_s5U*{U zXHDlj9rT;BdnKLP^f4KEZl+2)HIiPhgsif;d@kNl*eu>|x>Bk6zGnAtsqAwyJLovD zvw~{x>L@iybxw!vCC;2fMfT2jb7bM~g>8Uxt_=>ph;ERxZsV zl}js4%wMG|x0rf9_B4Gt69KIP>t@&L{o;d@six3+3*SN2&8~f~?aqs6LSppn@kXzI z(b;Zh*_R6FEyxU{2Qs($Q$E=5C`aI(`k+W)U;<*y=w8jC({(hOhBsV&Hk~j?r z#`+D@PZDc+S}&bi{D0Yp)%W*an(A{!#w!9tQB|tDBySqzR1|h_|31urcp=ZP%^ji6 zZ(gU9gbQmBq;+r?LGgs$*UC zgW&gWse+GTr<(O!f<{ZYB^wgKqaL@BHVPphfb_!aL*B@OuOaRDZ|LNLW(tQI0)5U( zac|F`3LQj(ks;pMnCC=JOEd-@yuy740Yfj2kaLsyt~887HaQe`5|B4GyJ@xZ6{lvU z9gci)1XJU2O66}d3+0!vB5=nMgfk`IyGn<;DJ^xj>{<(^=7O@}&fKe{Vhf3*Lm z1rOpSws$B2{+^K_D9ND72JLtl6!@UyQ|ul&6{!FCKA&+At%`A>I|b4(7aj(;0)m1p zD&=dvWAV%J=fq3&Y(eVRE9G&fg&Z#{)(W@h-LeP0u!ps3Z+ddo21kvK#i5Q5v5_E7Aw zSA!a!R-JhwgMI5xuT9o`7<90^us_IkXsKNJBnM?;?UT6qE!y7ZtG?KGc1X_7 z;|`e^278yb)(1rbki`3~gXa}6uAJmY7wW79dfB{UZQONTGo<3XuqH&II*cW;kb*_l zCBXaF<4t*&wpylAvzontyViyrnEmyUA(_(P2S?K`Dmgl1Q}9M!FZ(HQZ24fGGbLl# z3j8&56hU1i1MKx|7k)H6T1`mK-@wF|lu>^1(bNmD<%8`T*feo{*HXzXzq3=)Ey`h9 z&TCLfsYRuch|ig|+^@ua7Hp@TUV1kfaO*5uVDLG9g(CVE-%G(UJMgO1VV!qfSk2Nle@ke<+tpXmX9}jG z;o5M0&WM{HAEAd3<%p>sKUeD|!92Rv%k4PBoF%X$@uHbiS#*J;&qe^>c52iS8Cr0Y zP+uAmimAIc8L&OM>#!{ljY>EpKgy58TG7w7VT!WE%#`8vES=HZTF10LtWQJzFeCQJGKS1M1sb4IZIWcU)jVzVf1l(5Ihw-=jT{2a9BiC^P3CD0|MyU@0ezfYMw z2fShHuG{<~KV!HzQ$uCbu2Sq6CfxIlLy1|&4foy8Y=4ygG;n|uZitv8T$s#Y&Vmo6 zcHlD$R-k*@q7?InJeT!y?PG85;8+V#nd9Ioy{_{EO}S`wLnYjn#ogOB4I*z;@yRuX z%q80=yu9tO@k)Gretx5xd)1Sj+{or@e!fhUVj@DRnyG;bl8uYR$wre|FHhB%V22`M znmuB}ato0%b$0J8Aa)Q_I>HpUpOb-T|K~kXdjZ3`*hl(g!bAtKXyyu?85aDB`!lhF zMt&EC#w^X$^u-9y`uwtZTU^m8M<{PD*or+@%xmnqC8qVjwT;svO$dQS)SIl286vf| zHW+eC)Y$_weBwht7qjPVS_zqEXRc8n&(zv)t=hFoos&1yhlA|o{rO>?OHzoLDE60W zYb0(74dZ-NcvEopnAuYi{-e#Q;#e9BnoIvP<*;&KBGy>zHlRE1w5eoCf+Lz45Dcw; zk(lP}kn;+hw?e2nl_X@Iqf^)SbSXP)*$AMM!Mgx4ml?9RSlW z<3&dll$U-sba@i+IQVjVR|IVZnS%E^IxycK5@so%khAuYLyXlf{pHd&lNeF${Hc2X z%7)G$RdLqXU~t3MJen!X4kg+SIV1JM3PAj3cz5oXv@-SMxW~p31iv~iDxE=ZcJ+{! zoCTpsgpTTtYV(s1Ya*}_9XHi7g^~2GpsBUt+UM%}M9&4%Yk88%pC`Mr=am%bzaE{s zK7eA92&rLTB$mqIi(S#f9oz8VFd9oJwfr#XI&f3e@54K_9^#Io4ij=GNq4pFW%}ECN0d6sdt9nUx~`gmUh;N#xe35-P|fGw1Im6@i>>XN^5DLlHO)1N4+ph={iIW_?8wElHOY^e1XTesB z)smNJ^sU3QzOjR3!;&cRGw~?7fkYB-ErLPFS~WFm1FX0#*zs`ztzU z{mR`PqSDG{_}b4mP^r-2cE+wnvyyoRv%0J*=pxB-=azOd>vhrToXrB_}la^B_<}?TDL0*Lq zc@ejJd<%D~va9_f)&xn*9#`-LcBNV+Hm7olA zl6bE9%dg{4h{zdzvxT{yK$h@4I z@?knc!g@Ln&O0<%(w}e$-9lEx5P?)!LO9w@e20mJ>5`Z=$1FVo>8U!)U_a{^%zY$B zq;$b4SaWH4Zbla(yd$8)4`%M(Us1mp#PY64BPSHlForj@)|CPDZIns@jP|G-bJQyS zeD8EWfeDjILsTiNM~W=9N%5q@f09`@d$ZayxOOm<8e$o5Xa!bQ#s?b|FUH!w@a_xs z%d1SIX-@7HkHR!;R!Aikm6HA>dqY%bp>(rtySiXxk3dOhR{HLEUZi5G$Pr7O@%v_! z9JI~~bh-e(WM%wVkxY8AD$GqkaNA#&uJiEbr?RsQh@7reIzI^luJ>{Tw84{2=ZNf2@`b zbSkUf%IbAT?m!pGJmrv7`_uHzyzAJ6*o|X5BGG1{jfrS8BoRLHLz_cDm%0_g%xmIM zd0RDK+!%=aT*y0qlKDPtT^;h|VP2Ev&8L7TOA_+z)Nk#8w=GFX;v&<_PkM01Tk?q> zO>r9~*412^iU|L+fA2VFq-jN1-f2)ByjfYCY?JfLmq~kt@P|N3i1oRh1BA?-%-x}w z%PtoK5u@XpMpR~pog3akY=t&ANWsV;tv1yp2KD;wDVV@do&G{&)ZZMU!cU=|V?)9z zJY-Xu%C2g15o08FE(nn!7g+VJVEbu{JT)Wubil>bw3XHF_ra7WXf423=JwJ>;+*#cWRdC zm%YG(<)4Z;JllAKS(kst%oapT2nvuxJOr8KwMZXBRM)w-YuLJ(@;(zNxlRoQpR%k= zlPsDot{flwF=$PCE=R@M*4w%pm!-Vuw(RFD5j`r_q}&;K&Y0ZxPFE28o||P;{a*OT zq`%9rk=s|=l_c)lY`$LK%b`Xobb& zw_?PJTCGK%w*wjZfa|?4l?{eMRe8doO_;O^Z!&Fbhevc=G-JmQEBI43$+h@1%Afqx zVHb&7K7H$N8Z~w7p|HvEdaUVVtr{FEQqMJiR#VA)1Yt3@4B9oPOs!t?x%j!DPX%NX9rHZyUrA&i!w+ankek6bD=nlWH`Dz6MwAqB-r-b3^l{O53t!L zr4xAq=TFpy1PCxj!fU)_h|{`_QZ(g^R>`|V#BETQzfV@Kg~*|Tgj z+yKtn;K#TTgVrsyd~jjYN~UihPxxW&rZp=I%?D(Ze7<#$Y@uR_OT(Fnm<_$)gX>#g z&d}l_V5@Ns)|{Wwgp{Lm$zAv`?3+lEl$qDnzw^2Q!oHiF*)qrmydOuHA`I5WQVJ8y zaO@nmJ+7k+X_7%o)5(z{i)}vSN(iYajxTh->>7P&?#I&afUW@H*OXE+%2a)|B_d$rZpoHrPoPKC;}gQhTi9-B6W0L*4eudks9tL7m-3=&lnD`t~DS+Y!T8ys}B zK*8J8ZhPZgvHW#FxQ+3|LpxlK1<}m@zf8%t~*~>Y}vnT4mc5Bg1I$Y|AOr^G^ocR4AB%3{gmqC|*uopOFFLx4E`bzE~mgN>#s$HwlRvi1*zS^r356z7ZdBfJOBFK|{MK%!m2i#G`-es&Wdpa65}8spQJaoS z0h00)lNH9hN3Dp7tO;Qk!zd;&_*9({auW_@>PU$tv24~$Wp#^g8?HF-wnchV7uJGsoz88fYad`& zi>7u|$0zazx~v?#yP%X6g!;VqYcT=Kf!aU_jHnjaVFUIFhQP4Y!z>yccFXM}Y z8A{U>$(LHwW?7kpALY~eCulo|_hAE1#``@;519$h_(eMp#E$$!$K%G@Z(5*x%*m(_ zF67K&8a{2I(e89h)JNAglhe~NXc}}B)pGeqSn>k$;%eq4m|lyA?VC@*R< zP%o}p=8YoMHDkbXV%+pRlMczYtEo^I7&^a^ko)q3*y8s{HMTm8Lm`zGL~&$j%v0ZE z|04e|Au;jZ)X=k*KFF9?#~|4a_EOXP`<#EIsBd(eU}Vt%&YzvX-sH>fGMAVfskl<_2xU>B_yeXc%=$$mEthvv_acI zhQGNUrpRHutqX3qRE>Iq%fPOtfLpiEhNSr3!bHs#z!(}_Yk}8pE@J6OnAr;|@`t{? zm}@A4kIBK8k&C$fFBB~%05`in;T{h&ChV!~qu53dEM34!*sbzc zar0rj_gfUptk30}4GL21AhLZ$H5@2w{Mo^wi-&f-!^W1eEv}30cvGcXoDu}VNqCKP zE$v18Dkt!f#LgRkX(J;wcxKM_{21Kg)X177GT0qD8q<81+NhgrG2McFw0}MGvHOD9 zMcAdd?cO3p5KJZJYw^Oryx=zaC#k+uSNbVaZ}7vZ`;-5ZFH+&e?F>Zaq>xL7`39CJ zLv5hbS@kL?_@jsk`M#7}uDS^vrpxk)0o>}d3Z`6uAL zPC%?dI)H-ciNRobL&sm9d+rc%M-Vz&jortLOyF$A@sPMBPZ46Cgy8FTUG zUVh>L@98UCy0Fky1Wrb)nKS)Q(H52B)j_Pz2OJ4Qqp5_*eE|P6D%iFkWC^r{V&$ZQ z$9+Uy9Y7tYbrs;3)c}n|9zIE4CK(?0Sjqi+iIv03$(*!FOJ2Udj^ZAHStNHYEMFCI zbZ{VNym0@1x{d$=KI`*p8Mqo`hD5>+AED5ykI=fl5SDqlbF_&2aCzm!5qcdI=MCaF z^o5dS-Mar^*sf+M#0;b(gg7#EVx~8uH646NXx%#C1tkEMeo;A<&tB7|{ltCbeN_MB zh=2c%z@fR!KW&2wEov(PG)BGuX#Gc?DwQHqswMD;54JJ5`VcI8B$_RY$Y!1dUT8810%2r~%&!Git8L8nSz zIeOt~xR{CpfMeeE16JhiPes0{2P*zO z?f$b7d6#{r#?Wcqud1`~Js@rJOfPu*b|s=1@Kb*}{>k0E<#DKj0FgSoprC$m6wtlk zDYI}5tkHEMLiC@L`)^V55(M7Bj%W1lj0{92 z)-$M41~4qc0G9zcv42o3?rVl-+z@_4BgHhD&ZNXE;@*DuA1=@T1@Rf;QE{MhuYFAUB2I{fi?tV6cq$3me@*o0~rHAv1u!=l=P-fjxfD_f$ z*|`=2=er^oBboWWwik)$TOR}3MML03BH*M|eSut)pLhW^>!Je~jEb|Q&0!c$~G2xx`jHd?Y$ zQBU^yPwS6l0)7A8Uz*JzU}b#~69d|CigMJ4jUv89ul@aF{9_}h3akiH8e;$%#5$uG z%?Rx@01?Sp>*+O>a+ANBh%DERS=2=S%Wwtu!>owYXf>eQagY6e@J>A7&2D$|HbgyD z{W01H1cf30e#`yu*##JJT0=}>G859odLagF3(^m-|^4fR>5|NEd#(ZJXnjA)dA zyZ;{};Sw0tbAq?t{YyIrT+@JU0+8?Jrzic}<>gFXwZ8Dw jyTPaYZ>KgR82OuMa4l!^BYh_v2l&%e)l(@|wu$;bY!yZU literal 27974 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 m8D19z|9^zG`aSd&u6I?xO|NLX6!519Sa return if @_emitter @_emitter ?= new EventEmitter() - @_emitter.setMaxListeners(50) + @_emitter.setMaxListeners(100) listen: (callback, bindContext) -> if not callback