};G8IkW
zR~(5iQCl=(h3Q}#>b+fn`oLL>dR7jiZq4_oiC#htbQ5*2Lspu8i=u8>vb7GXeXEu1
zzqYy)32jwBtcXidPxmR*#Qs7}z-N_NVHidcmqK-vhFWne)CBsY+Al@z%qG-?KSA~P
z4Qk=%SF!(keIAgA#HXmO30`gTQK%Khp>`w*)j0F=G$rvs^e9tiS0%Wa0)fSYp5N&kNPAlw3c7M*achSd#H!<
z88*Y@b>_=$9BQ0>sMpoKNTman7gzw>tv3!sz2|dKD_(%wi4~~#egkSETTok^g}Ud*
zP!m6Ey@ML)CF+*MY%tGMY2sZON`CmNzU=!x2*kyr?)pe|gE>Uan0mK{P3eB7SD
zh`R0$>aBQ&nsDxoX21~Cjuk$!q*R8`4m&!-B!3op~PGb|iikXq}!P;;N{8AJnZJ`T_f|
z4yKXNYk13=y3723yw;%_Uc2r$kZ)5$7lWCncFW
z8|*pU0=9!Qgnw}I5mrDAs>7xJ4y6j^FXHLgfO4NQz|+F~(WG@eCa;z9_IdsXie&n~
zOT98q#5J7%+p*}a(w^VIo>X7jG^G4Obdl1+w#}eEjJkGA$8QEFincoHQ##suLE7D-
z@LlOSV))Ao>fE3-q>SfWJIYnc7|N$C(P_%XRXBNqgpSs>v;NeJk@NRt&7)9@xV?>c
zTi-_Bq5nJD(`Fat5SgbG9!IAtv5xB2aK`9Od7be+M^}5IAI5W{64~{XJkJ4(^Z
zqGLbxGnBEEZj?*p22uu5*AauG(4T8{+^3xL)cDt2&L!J+KaiWDTinqm)JFea>}@Yx
zW-t1L+(YW+ZC>djwqBNVT0=`p8*+V!tE&OW6Y6uZF!?grfmp|D24^w4sW$l^>v)p2
zDLaX)aiLz_bc&7^#6@kp_c4U{HXh;J5&Y8A%KSez2kKhewlMkOluY78@(Zb-r~Ih7
zkEEg_!ZvPfLeJm6Hh0>Zed=>6-jwQeR+F-v^Yd&QK1G}#sr%T*zSK8RW>MV#h2pGIX)GfEf_$_qW%q5qFklE2=$RN5%byW
z37x+B!|{r;QWf31Lo_Of191#~N69{_Qu&Vj6dX+9r;774mSlE-~b;6UxAKG{b7qlS$
znfMgtJxT|1704B!-kZWN1J9Al-^#?(D2*uPX!jA$CVvxk47V1s<2#>_yiT$rjkAwl
zRKk_Bjg{X>eJHM??4~{hM^kj@Yd`x)q>_vC(Hh()yHn3g?%%}a@Djx{{$vt8IQfc1
zgl)VZ1Bn}vUyrLPI*L&WQuf*S0QDi%XHpI;XY*~aJ|%#ZjwS{tl>Ty3?BP1i2tFhF
z-Cn2@z7!ww4axnJvW`-MTt9M;aVW9p=O6V@>QNLOZ%~R*UqE?AJtubMnp4zuWDw6Z
zRc9gf{5e>ED-uU-GMgYyeors~bquAGmXveEzfqo(%Zq!>B)@ET^2MtfN$>oS-bF
zWFIeSdo4S_w)8j5<&Tb7gXcd|XHnll@#5Teo9~BPDDTpVj@j0GCiMI*M*GV)A8ai}
zt~~W`X>pK}K>3vT0nS19OaAO4ScQ#gTpPV9WvH*j&J-P!@L#t62k{c>5wxjB{T)gk
z;!*Z|I(Z%4DAmZ#L;dpVNq#DE6KsyP^!%;iL|qd9LLIFQp1*bYo6p9*@fjEG#iy8k
z6y@5N1UJY{!W_f}DLtw8uQS51}-iO8t)Q
zs0Z~osK?PZ1-~Yaq&%R$j8cZ8qY~#oHdSXExj^a%@NG&R+eX8c)%&-}CfeHxEVl7k
z>m&S=b}KN1GJ^W|IDoR1qT@KFfv3i&A2~nUS0=e`ww@Oob1n(PC?%-7xu|?aqfV4s
z)U%KLR6d|V7NtD(E~w)zN<8%h%1uv(?*^Pq>_urp(QyU4VwjCRN&b96nMUy;Us3nJ
zl^wJy4kr04CofQ%+6(_lJvZm-Voh@Oa34iSJ$r2zyiDAQ^RbkYlo)$%4*9jjWr+t+
zdQmTp$H*t>{r`$YFA{CB3rQV`)c<~TC;m6(Hpvx~J=F7J5+xVqe~)b>M$l&)d!h>U
zH@W5qN^|O)$zP+Mru*NC#NUr`oY3(c$Kr>Sx;D3#`rnTW&lv=VUnb*Reirno-|NJ(3bg9EX2VuGse1F_ZiV
zay&H;DtLQkc~$zsH|wt&!I4?N;%Xh`xgd#blkI
ZmYFXnQC8U{d3>@utVs9II
delta 13879
zcmY+~2YioL|NrqzNFqo=#EAJdGOUKR>%$sP{s2i!#
zsw!@(DpjMDs`hqQTdMqC@0{cD_rD&G<9W`x&iq{Gy1weZm;UJS>pc(m_W}8qJ6w}I
z9H$IkFX}kG^E%GjP}MrlZ}l7}1^f$v->?OC
zY+`o0011Y(30-&zu(0eyGDmyP>w=1j6p?W9BP6$
zQ3EeRJ>#XQ{#mGYcTo}h9X0WD)WW@5m~nkk{ajcQTeWbT4g;xB#~93qV^N1^9BLtN
zqdF`@?PMov!Xv2mU!Wp(9u=AIP~+W1wY!hnz@Mo0UM)=|3%beZwJC!-RH3MbGcf}*
zPy<$Isx_n}sP6gBW!Tc2a=@1y$tfxM|sf!2-_j%~0!rlKZ%7uA0)D&o7bklz1;w&E0O
z;tRHX1GVD^sD(VW_dVN~1s6pPSPJz4s*YM{OVl`BQ6HK?sI!xb`Z6v;Eg%yMF~75)
zj8=FYJ@IqYBRP+Jyqp`TM^Lh@u_CH{byT~0s0mwJd)WG6n2-8#sI!rVTJQqYhSs55
zE6yaN2|l(SvwnfP{~y$fZ`$%h)WlD1y-z#ytOHRCu8G>nC{zR!QDP#(0&9|~0
z@%JXPkqVh<-HYmY5Ea@pwmt_n@QajMXU4CyiA*KbIAN%T
z)kpPjjsx}ncO#<-c3=Vg2n*sdRKqW^D_+Ok!_>trq!Vi415l439@TF=>MfXV>pw<~
zdlg&^{ComIqZsxKmw{=8miq?TTVxf
zw+Q*mld}m6;WgC4@1a{?q^D#Qnqu9I<*cEoZ+9)!KyP3f?1vgC%{mJe!6m4LtVUma
z9~GHhs0sI>#`_HY@SASLUpu)=MGf?fG7G4S>d*u=a93OIXB~su=`?iVT+{+Hu__)#
zZR|d3e9!J?oXV(n;i$;H(Vh5f#hs{7XuG3U-Ve3I5w>9pY9Uimk(z^Ja50ACQ`9(N
zJP&1!H9U-Zy-uJ8zK#m*6VyVV
zS-pFjzYztZcG?cL(?O_-V^N_`KrPHYjZ83^g{X%6tcOq?PM{Wa7PZhE)Pn9|06xOX
zn5UNsc?fFYR;W|o0~MLUsD3f1amOGVa62jX#w64N+^7|%n+DDb)DGW6MQEEXe~fCE
zjhgVHt-pne)UT-aKE2KT5~u})+HyDs>ius?>^>BR~r?vb{K-)QIBpC>hLZ_KfV9!l);^-FWF(#1UaY)enfS6
zgxbL~T#R}8@^=8tK(+tWdJ=Uu&S6o!i0XG2wSiwy5qgPkRRr}jA+Cm+s3GdvwMGrl
z&DO`D22MhqnN-xm*Ps@ViF#CfF)tp)1U!M-NUi?HNL2e){fWO`i;h&N<3Lo%Mp=_l
z6HP;P*n~QC+fmQ^q9(Y8>VF$U@fWOy#Rix!YD?5Ov8Z(P@(o4XntOcq3+i}EieLgzZq%)ZQS-oH`KH5
zhsAJ;H3K!k7Sx2hQ5}z>JBkpuE>bMN6
z;##bMr?DeGv9=g&zH|$)HT8!u5MQDmN#GFk+YpNUCxO!%bw3>yxwWXbY%3}PyO52!
zo&98VsE(i(a@_g_YNwY_5y(O9_(#;Ce1dB4Gt{&TK$Xj&+6AL_9AWEQp~mTiicC)|
zp!Yx8R>Y$^OtGe;7Vs`=;Ptk=6}6MSsGS_ZP&|rich~wW>P-EGI-~`LnMWIhT0l)K
z;wICSj6&EA6|&)|9Zp0IumCmiIt;-rsD++G?dTc?;VsnJd5)SOAlhueg^Ea3LUqub{2=xg5#;WKs
z!aSN9sL0gCF4!2m;yhcvighT5j3oXZWcrUZ0}ev%V6^oRcB5Qyl=;V_fv883fm*<7
z48tv$AJ3x}dKG)&9c$!h^KVFtu_5)hP>;N{dyLs(IJ&54f}S`SHDC;SW4x_TMK8)z
zYi2QD@_C9EQcln(-!}`nlgE(6w
zo{8p*Ru2nM?u@0eFP6j1~FfXX!hvjg6Ab8HvYIl&4_`u0$f_c8-$K07b`{LsT7m
zQ0{?c@k6YL*{CnqU95)xU^rG8Zx+%ID^pHIg?KgU{za^bc{pHou{KV^I84?1|9x(T
z=aa&2xN!#OqAQipF=k?C^hh&@uN!ut9ETck4~F4w)WQl)FrjUT+Hp%%qz2jgNvN|k
z6N@pwvzUyY)d$ucsAs+pbruexLVgT=@T|Rm87ooF!NQnlqB&FnSb}n}EjPvDl%p^Z
zM`9VAhVG(dR+FiRyRabMLaqD}Y5_jPOWy;3^uwCykIhgE?`q4vu>|EfEP~Uq0WQJ%
zcp8K81#0}tlZn4}+I+GJSvyq6C|e$mRVa_ewzwRN;dN9b9-|iW9JR1QQ_KXVQTqs(B0dW>%DmTIs(~@8@Tzg`Gov34cJn4UbTfD>B_IGzitN
zHY$Q`P&@34YBvNm;Rw_jn237R?uBF&!d13n8*0M+s1TpV5WIjv_?I={P4jwIN8Rs;
zC2>6JHJp!{cn>P%2T%(-fm-P2NF?1(4jHZNf2ft^z){BDNB>u$`z!bQU$vV{5**h`%a|lhI1UP@!sU%RNv#iL>>y
zP!U*-E%77NDgP5S&OfNP!+*BfKrm{7wNV>si8>1%P>-V5Y@WXkO$-$Z@ig0D6Xv75
z3l*w;sK^{eO>hRa(C<+Te}c6z{~U7&BT*6QfmLxJ>QTLI>(`(nw0REkSI9o0LK9s>
zJ=?pe9lbzJQ21?gzY=P}HBmcgk80o7)+eEMI2X0xW$20PQ1fg?MdBoC{Bv$HWy#z?
zP4o}e!@}w2S+_y0ybr457}U;_Q45}DU5?uEMjVCP(Ho1-H4!U~UX*KNer$-E*WHqg
zCK!r(zffl|SZ1D?C>XV{8mKeU8g+Jtp&~Th)-T8Ml=mW$
zbUPQwXaNsUKZ`F=6Be9rI)lsq
zHK_4E#G=ga>?Nbu~HSh{-iu*AiK1N0CPgDea7MTbI
zqe35!ibMp4VHd2<{LTb2IwYG>hbj{b;U`!hPoiF<=ct_)T5J|p9Q6o7Q46Yt1F$P9
z5}CIC2v((h4HYrZC3a!x_N5}6j2bjSg>EG38P7s}aJHd#eh@YAIn?3$0rfWggjz_R
z3{x(E>R$=fuLD-c!PpSzqau}^LHyO=G8F~!J}PuiPzx!t)I_8@DrAjOk0KTu;S|(s
z^%2&_bg>+Ij&s&v)p;hp3JCy5BV`t%N!QjW7gTpavX?n&>T5L>8cS
zyaglh4C=LgfofNBxj8#7)T60^dJWs6A{2uem((iGHZ|!>}lhM@>8jwa_J4P4E9IG78maSPOGd1Np78
zp+pT-11n-Ptc}rF0+*p8umd~dC#bh6?`jjNa8$bv)@ZCtc{2Lw{oh4KD>{IBO^(^}
zFZdzlKQI#4t}zo`LG9!=DiXh-&dO8NIK|#G8z_hRu+_o1s8O+}b65(WVgU?XYff)@)IuUK4V$AP^%1K7DfGjOs1MIg48%O^%p)qkj`(Xu
z<*3j^p{Qrx6E$!Q>e(e&XQJ9KM}>SnDq=e@04=Dl+#_D}IJrkpKH;=Rv5~s3w-i`l!hCu=RschcFfuk$6=9=~xrf
zQ5!qpCZh??+6F(^@&j9bY0Ewv%-c~8we#vY2qRI4as}!~>mX|2?@qgh}j
zRK&tjA2jzsGHu9gz#e!P>tf_4^G_!U*p%{N)I?9Q0+!iq{;8%JmZZGKnuU7bzeMf$
zA}SKsQSbj9RHW`B5q3MjlhHHx{=lrfgtZ!KqUNYa5{)`k<4^-k!*ZC8dZt@Y<7A`0
zBbQKz_9m+Tb5vvs@=EE^mB#?R{~=`5AQIKFJ?j1MgIf70%$*n&x@oA1GEqA`h-#mW
z3iV}F=pWd6uPx>*l|(I|8WzLm7|8riZ!%iI7}P|Qu{q8`O>`19(Pb=;H&7G3L>%6xY6G>g12)H=I1i^|4o=2_+sv2qGP?D;_-691Vq;X40Y)LGb$
z@%R&V!QMN}TeKPLQ$B<`r2oYN_`>S5)BMM7AkL(I*G}TE1~qq?*Q62pQtpI$cKvNR
z6}>3W!a6w5mXDzNXJcRd3bo^q-Nq@X1$~8i(Q}W9un)#jF1CmGN0XUKh0MX$*!*AS
z12G#F`b8LyD{cKL)U!N~>USIUI=0zs+=MMCzeKfbvCnL*7lu+Ej-EK*O-7;0Kz)(c
z+42_jrkrIxj0GuY;}ATLdhNoqOuu$mg>n@3!zrkRUqT(u9L$4NNsGyRhM%B&mTI}S
zlYS;$P=PCx`hnQnBe&=bg_`8QHpSdOhx6w{+KndVkWa)3v?+|~BwhOKdfGA8*}CI6
zfO?)5@#pfO!EGv6+Xl~bYxyCe9AP{2WOD!SdA=BB+btx2gH((*y{Jnf&9nCu&6%V-
zBwfSoIK%9H)#djv^E)S~mMy=n9$a%M&%zNHLaIk9!r*JD`<1*O
z`5&=4>dGSD%jRRq&!z4y)b-qLGoDz36iekm8t2Qs&A(JqH;jBc>JA`pPVS|jTU~WY
zI#4lof-=_k=~tdKf_v3TACq)lA?cTLEcbM|yBeJdIF8Qqx$%fRuWasBhq`#`s*`$<
zzlhQJ6LY9_&hbP?Dr`iGkq5LbU6m7ih7zgaV
zt@s7^y4$k4E+pTBRMXVCoz8Sx%Z)HnCo1*RsH*|_WILeCsxKKIKBqqST2gmg4Y`U?
z9#8ok`J&`YkS}ceBv95>)ZnzRWm8-h9_Ho#j;bZ3hPI1tC6EG0vDD9at;<&GMo~_|
z{Uluhl*4S_J>;XvXX7^{U9pr$kPee?fxB#d7s?|&a)0T}|IilBjWil;;YKjlS~fnk
zsCyH&{~_I__VueUg*DVaCVfe&M~~ywjU{a)eL`wSeH*OIy;oOl^50PK;oj@lQ3~Bi
zOKjzOEScxESEMl&{LndF8KCrQ19r6evbN(nJ8(7X|FU($-{wQ8FGiamDUT-qmaT6_
z-5Bx>NIrJV&-2(%bfT?jWc`W8Z<9i7=Xb24KlS5Dr%11^@5$e%kRL0Nz9y|CH74m=
zO}a_GIOziEEagEsPV;|Gsz||`w2kyXlCC%K626BkRAKA$;7-!Jq@pa?!`9EH$$9b{
zNM&qY4enp0zAbLTa`+~;!pm6WL;k2t;~`Y&x@rEPPkpWPSUQa%&B*Qa|NiJkn^P2PkScKh)fGu5lyW;v
zqs?`!Lb*NpCgf9X+p78%s7OUmlCI5^2XM1K`JUt_l7B|NgKl#9QWr*=OS(^bhm=H{
zH?bV43#lpP5~jH`obrdH@wVKQd=>JUqzWYWa2o3>!HpoBe@Xc%DVe%kq<*BlloPmr
z4JT55bxpFF{`e6ol6$qVk!@4ej#(VfP#-~kSyCtReO~>jcj9IwX%UsLuHVRPAf?c_
ztsSf_jM0L*BcDhQ8lQmCaF1nzQrf_>KbJ4pQd6tsgAvO1&7*uYU@vaH;%OT
zHLtUc)RdI10$1E?1FKw@azFf&)P(`MQa(Yx6#hbrB0rC$s|okJlXQ7;Zyza|)R*-7
z)ra!lSHBpSC`=%=BpoK5B>k7xqeugkCsiXqjr0fk)_9EcjC^mrO49Xj(roI!$J1CD
zui*|K*+pGCxr9FIzduuD%N8{^Wn)eqLMG#I_k@txtWty+<>rwax#-
z{f4AMYUhfMjg5<4wjn-Z+5UQ`ysN~z(o*75vXUcidX*a&osu#!DLK}a9G4Q8>WUwo
zIM$UCmze5GO>zaNWJNUzEL~`LQqovgQnGp_XZ7h@$=l17GAb^9L{{>U{eJ!$E_HPL
z=#=Qx(MgFZS>+OTc-QHj$WU>KuGlzNa(3qE#L=mvqhB>~MZ2;yQ?oN&afuU>CSn
zO?5i;fxmCs@c7X&xdYvru_x=`?4E_aOjVZu@`9d4;zv(Nj&miYxzZ9{F-ZyIQnL!J
d8Q>ETmzqj-{H+
Date: Mon, 4 Oct 2021 09:14:04 -0700
Subject: [PATCH 03/11] f strings for activistreams tasks tests
---
bookwyrm/tests/activitystreams/test_tasks.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py
index f4c85e1bf..1002e4a8a 100644
--- a/bookwyrm/tests/activitystreams/test_tasks.py
+++ b/bookwyrm/tests/activitystreams/test_tasks.py
@@ -141,7 +141,7 @@ class Activitystreams(TestCase):
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
self.assertEqual(
- call_args[1]["stores"], ["{:d}-home".format(self.another_user.id)]
+ call_args[1]["stores"], [f"{self.another_user.id}-home"]
)
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@@ -164,10 +164,10 @@ class Activitystreams(TestCase):
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
self.assertTrue(
- "{:d}-home".format(self.another_user.id) in call_args[1]["stores"]
+ f"{self.another_user.id}-home" in call_args[1]["stores"]
)
self.assertTrue(
- "{:d}-home".format(self.local_user.id) in call_args[1]["stores"]
+ f"{self.local_user.id}-home" in call_args[1]["stores"]
)
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@@ -189,5 +189,5 @@ class Activitystreams(TestCase):
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
self.assertEqual(
- call_args[1]["stores"], ["{:d}-home".format(self.local_user.id)]
+ call_args[1]["stores"], [f"{self.local_user.id}-home"]
)
From 321949f2fac201ebf66b0cd480e151f63f377769 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 09:47:33 -0700
Subject: [PATCH 04/11] Lightly updates tests
---
bookwyrm/activitystreams.py | 2 ++
bookwyrm/redis_store.py | 2 +-
bookwyrm/tests/activitystreams/test_tasks.py | 3 ++-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py
index 1feb495b7..f843641f5 100644
--- a/bookwyrm/activitystreams.py
+++ b/bookwyrm/activitystreams.py
@@ -480,12 +480,14 @@ def handle_boost_task(boost_id):
instance = models.Status.objects.get(id=boost_id)
boosted = instance.boost.boosted_status
+ # previous boosts of this status
old_versions = models.Boost.objects.filter(
boosted_status__id=boosted.id,
created_date__lt=instance.created_date,
)
for stream in streams.values():
+ # people who should see the boost (not people who see the original status)
audience = stream.get_stores_for_object(instance)
stream.remove_object_from_related_stores(boosted, stores=audience)
for status in old_versions:
diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py
index 521e73b26..78f373a2e 100644
--- a/bookwyrm/redis_store.py
+++ b/bookwyrm/redis_store.py
@@ -35,7 +35,7 @@ class RedisStore(ABC):
def remove_object_from_related_stores(self, obj, stores=None):
"""remove an object from all stores"""
- stores = stores or self.get_stores_for_object(obj)
+ stores = self.get_stores_for_object(obj) if stores is None else stores
pipeline = r.pipeline()
for store in stores:
pipeline.zrem(store, -1, obj.id)
diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py
index 1002e4a8a..887047830 100644
--- a/bookwyrm/tests/activitystreams/test_tasks.py
+++ b/bookwyrm/tests/activitystreams/test_tasks.py
@@ -125,7 +125,7 @@ class Activitystreams(TestCase):
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
def test_boost_to_another_timeline(self, *_):
- """add a boost and deduplicate the boosted status on the timeline"""
+ """boost from a non-follower doesn't remove original status from feed"""
status = models.Status.objects.create(user=self.local_user, content="hi")
with patch("bookwyrm.activitystreams.handle_boost_task.delay"):
boost = models.Boost.objects.create(
@@ -138,6 +138,7 @@ class Activitystreams(TestCase):
activitystreams.handle_boost_task(boost.id)
self.assertTrue(mock.called)
+ self.assertEqual(mock.call_count, 1)
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
self.assertEqual(
From ac70a810af9cf5136baf63525d34b8a607e8b447 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 09:58:05 -0700
Subject: [PATCH 05/11] Boosts by remote users
---
bookwyrm/tests/activitystreams/test_tasks.py | 48 +++++++++++++++-----
1 file changed, 36 insertions(+), 12 deletions(-)
diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py
index 887047830..80b0b771d 100644
--- a/bookwyrm/tests/activitystreams/test_tasks.py
+++ b/bookwyrm/tests/activitystreams/test_tasks.py
@@ -22,6 +22,16 @@ class Activitystreams(TestCase):
local=True,
localname="nutria",
)
+ with patch("bookwyrm.models.user.set_remote_server.delay"):
+ self.remote_user = models.User.objects.create_user(
+ "rat",
+ "rat@rat.com",
+ "ratword",
+ local=False,
+ remote_id="https://example.com/users/rat",
+ inbox="https://example.com/users/rat/inbox",
+ outbox="https://example.com/users/rat/outbox",
+ )
work = models.Work.objects.create(title="test work")
self.book = models.Edition.objects.create(title="test book", parent_work=work)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
@@ -141,9 +151,29 @@ class Activitystreams(TestCase):
self.assertEqual(mock.call_count, 1)
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
- self.assertEqual(
- call_args[1]["stores"], [f"{self.another_user.id}-home"]
- )
+ self.assertEqual(call_args[1]["stores"], [f"{self.another_user.id}-home"])
+
+ @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
+ @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ def test_boost_to_another_timeline_remote(self, *_):
+ """boost from a remote non-follower doesn't remove original status from feed"""
+ status = models.Status.objects.create(user=self.local_user, content="hi")
+ with patch("bookwyrm.activitystreams.handle_boost_task.delay"):
+ boost = models.Boost.objects.create(
+ boosted_status=status,
+ user=self.remote_user,
+ )
+ with patch(
+ "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores"
+ ) as mock:
+ activitystreams.handle_boost_task(boost.id)
+
+ self.assertTrue(mock.called)
+ self.assertEqual(mock.call_count, 1)
+ call_args = mock.call_args
+ self.assertEqual(call_args[0][0], status)
+ self.assertEqual(call_args[1]["stores"], [])
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
@@ -164,12 +194,8 @@ class Activitystreams(TestCase):
self.assertTrue(mock.called)
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
- self.assertTrue(
- f"{self.another_user.id}-home" in call_args[1]["stores"]
- )
- self.assertTrue(
- f"{self.local_user.id}-home" in call_args[1]["stores"]
- )
+ self.assertTrue(f"{self.another_user.id}-home" in call_args[1]["stores"])
+ self.assertTrue(f"{self.local_user.id}-home" in call_args[1]["stores"])
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
@@ -189,6 +215,4 @@ class Activitystreams(TestCase):
self.assertTrue(mock.called)
call_args = mock.call_args
self.assertEqual(call_args[0][0], status)
- self.assertEqual(
- call_args[1]["stores"], [f"{self.local_user.id}-home"]
- )
+ self.assertEqual(call_args[1]["stores"], [f"{self.local_user.id}-home"])
From 2a88753e17cf094e6c54f09b39fbc1ef0e1dee3d Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 10:40:39 -0700
Subject: [PATCH 06/11] Chart class
---
bookwyrm/views/admin/dashboard.py | 82 +++++++++++++++++++------------
1 file changed, 51 insertions(+), 31 deletions(-)
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py
index e02b9143e..66dd9c90f 100644
--- a/bookwyrm/views/admin/dashboard.py
+++ b/bookwyrm/views/admin/dashboard.py
@@ -25,13 +25,6 @@ class Dashboard(View):
"""list of users"""
interval = int(request.GET.get("days", 1))
now = timezone.now()
-
- user_queryset = models.User.objects.filter(local=True)
- user_stats = {"labels": [], "total": [], "active": []}
-
- status_queryset = models.Status.objects.filter(user__local=True, deleted=False)
- status_stats = {"labels": [], "total": []}
-
start = request.GET.get("start")
if start:
start = timezone.make_aware(parse(start))
@@ -42,31 +35,33 @@ class Dashboard(View):
end = timezone.make_aware(parse(end)) if end else now
start = start.replace(hour=0, minute=0, second=0)
- interval_start = start
- interval_end = interval_start + timedelta(days=interval)
- while interval_start <= end:
- print(interval_start, interval_end)
- interval_queryset = user_queryset.filter(
- Q(is_active=True) | Q(deactivation_date__gt=interval_end),
- created_date__lte=interval_end,
- )
- user_stats["total"].append(interval_queryset.filter().count())
- user_stats["active"].append(
- interval_queryset.filter(
- last_active_date__gt=interval_end - timedelta(days=31),
+ user_queryset = models.User.objects.filter(local=True)
+ user_chart = Chart(
+ queryset=user_queryset,
+ queries={
+ "total": lambda q, s, e: q.filter(
+ Q(is_active=True) | Q(deactivation_date__gt=e),
+ created_date__lte=e,
+ ).count(),
+ "active": lambda q, s, e: q.filter(
+ Q(is_active=True) | Q(deactivation_date__gt=e),
+ created_date__lte=e,
+ ).filter(
+ last_active_date__gt=e - timedelta(days=31),
).count()
- )
- user_stats["labels"].append(interval_start.strftime("%b %d"))
+ }
+ )
- status_stats["total"].append(
- status_queryset.filter(
- created_date__gt=interval_start,
- created_date__lte=interval_end,
+ status_queryset = models.Status.objects.filter(user__local=True, deleted=False)
+ status_chart = Chart(
+ queryset=status_queryset,
+ queries = {
+ "total": lambda q, s, e: q.filter(
+ created_date__gt=s,
+ created_date__lte=e,
).count()
- )
- status_stats["labels"].append(interval_start.strftime("%b %d"))
- interval_start = interval_end
- interval_end += timedelta(days=interval)
+ }
+ )
data = {
"start": start.strftime("%Y-%m-%d"),
@@ -82,7 +77,32 @@ class Dashboard(View):
"invite_requests": models.InviteRequest.objects.filter(
ignored=False, invite_sent=False
).count(),
- "user_stats": user_stats,
- "status_stats": status_stats,
+ "user_stats": user_chart.get_chart(start, end, interval),
+ "status_stats": status_chart.get_chart(start, end, interval),
}
return TemplateResponse(request, "settings/dashboard/dashboard.html", data)
+
+
+class Chart:
+ """ Data for a chart """
+
+ def __init__(self, queryset, queries: dict):
+ self.queryset = queryset
+ self.queries = queries
+
+ def get_chart(self, start, end, interval):
+ """ load the data for the chart given a time scale and interval """
+ interval_start = start
+ interval_end = interval_start + timedelta(days=interval)
+
+ chart = {k: [] for k in self.queries.keys()}
+ chart["labels"] = []
+ while interval_start <= end:
+ for (name, query) in self.queries.items():
+ chart[name].append(query(self.queryset, interval_start, interval_end))
+ chart["labels"].append(interval_start.strftime("%b %d"))
+
+ interval_start = interval_end
+ interval_end += timedelta(days=interval)
+
+ return chart
From fa241b08e7f5502a4f988ba6d5614abd90db1e13 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 10:42:02 -0700
Subject: [PATCH 07/11] Rename charts snippets and add register chart file
---
.../settings/dashboard/dashboard.html | 15 ++++++++----
.../dashboard/registration_chart.html | 24 +++++++++++++++++++
...rd_status_chart.html => status_chart.html} | 0
...hboard_user_chart.html => user_chart.html} | 0
bookwyrm/views/admin/dashboard.py | 11 +++++++++
5 files changed, 46 insertions(+), 4 deletions(-)
create mode 100644 bookwyrm/templates/settings/dashboard/registration_chart.html
rename bookwyrm/templates/settings/dashboard/{dashboard_status_chart.html => status_chart.html} (100%)
rename bookwyrm/templates/settings/dashboard/{dashboard_user_chart.html => user_chart.html} (100%)
diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html
index fbf3ff72a..863df40d9 100644
--- a/bookwyrm/templates/settings/dashboard/dashboard.html
+++ b/bookwyrm/templates/settings/dashboard/dashboard.html
@@ -95,9 +95,9 @@
-
+
-
{% trans "User signup activity" %}
+
{% trans "Total users" %}
@@ -108,6 +108,12 @@
+
+
{% trans "User signup activity" %}
+
+
+
+
@@ -115,6 +121,7 @@
{% block scripts %}
-{% include 'settings/dashboard/dashboard_user_chart.html' %}
-{% include 'settings/dashboard/dashboard_status_chart.html' %}
+{% include 'settings/dashboard/user_chart.html' %}
+{% include 'settings/dashboard/status_chart.html' %}
+{% include 'settings/dashboard/registration_chart.html' %}
{% endblock %}
diff --git a/bookwyrm/templates/settings/dashboard/registration_chart.html b/bookwyrm/templates/settings/dashboard/registration_chart.html
new file mode 100644
index 000000000..eec909ed3
--- /dev/null
+++ b/bookwyrm/templates/settings/dashboard/registration_chart.html
@@ -0,0 +1,24 @@
+{% load i18n %}
+
diff --git a/bookwyrm/templates/settings/dashboard/dashboard_status_chart.html b/bookwyrm/templates/settings/dashboard/status_chart.html
similarity index 100%
rename from bookwyrm/templates/settings/dashboard/dashboard_status_chart.html
rename to bookwyrm/templates/settings/dashboard/status_chart.html
diff --git a/bookwyrm/templates/settings/dashboard/dashboard_user_chart.html b/bookwyrm/templates/settings/dashboard/user_chart.html
similarity index 100%
rename from bookwyrm/templates/settings/dashboard/dashboard_user_chart.html
rename to bookwyrm/templates/settings/dashboard/user_chart.html
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py
index 66dd9c90f..27edc3438 100644
--- a/bookwyrm/views/admin/dashboard.py
+++ b/bookwyrm/views/admin/dashboard.py
@@ -63,6 +63,16 @@ class Dashboard(View):
}
)
+ register_chart = Chart(
+ queryset=user_queryset,
+ queries = {
+ "total": lambda q, s, e: q.filter(
+ created_date__gt=s,
+ created_date__lte=e,
+ ).count()
+ }
+ )
+
data = {
"start": start.strftime("%Y-%m-%d"),
"end": end.strftime("%Y-%m-%d"),
@@ -79,6 +89,7 @@ class Dashboard(View):
).count(),
"user_stats": user_chart.get_chart(start, end, interval),
"status_stats": status_chart.get_chart(start, end, interval),
+ "register_stats": register_chart.get_chart(start, end, interval),
}
return TemplateResponse(request, "settings/dashboard/dashboard.html", data)
From 37cd7e684cb8b4f9d0ba4256043a15932b9315a7 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 10:53:22 -0700
Subject: [PATCH 08/11] Updates chart markup
---
.../settings/dashboard/dashboard.html | 8 ++---
.../dashboard/registration_chart.html | 35 ++++++++-----------
.../settings/dashboard/status_chart.html | 31 +++++++---------
3 files changed, 32 insertions(+), 42 deletions(-)
diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html
index 863df40d9..cd0ddc842 100644
--- a/bookwyrm/templates/settings/dashboard/dashboard.html
+++ b/bookwyrm/templates/settings/dashboard/dashboard.html
@@ -96,22 +96,22 @@
-
+
{% trans "Total users" %}
-
+
{% trans "Status activity" %}
-
+
{% trans "User signup activity" %}
-
+
diff --git a/bookwyrm/templates/settings/dashboard/registration_chart.html b/bookwyrm/templates/settings/dashboard/registration_chart.html
index eec909ed3..e98a0f18f 100644
--- a/bookwyrm/templates/settings/dashboard/registration_chart.html
+++ b/bookwyrm/templates/settings/dashboard/registration_chart.html
@@ -1,24 +1,19 @@
{% load i18n %}
diff --git a/bookwyrm/templates/settings/dashboard/status_chart.html b/bookwyrm/templates/settings/dashboard/status_chart.html
index bbacf3f46..5e1045fce 100644
--- a/bookwyrm/templates/settings/dashboard/status_chart.html
+++ b/bookwyrm/templates/settings/dashboard/status_chart.html
@@ -1,26 +1,21 @@
{% load i18n %}
From 551b49b903cfdfe8e63de58de788b67b320aaf11 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 11:14:50 -0700
Subject: [PATCH 09/11] Adds works chart and updates colors
---
.../settings/dashboard/dashboard.html | 11 ++++-
.../dashboard/registration_chart.html | 4 +-
.../settings/dashboard/status_chart.html | 4 +-
.../settings/dashboard/user_chart.html | 40 +++++++++----------
.../settings/dashboard/works_chart.html | 21 ++++++++++
bookwyrm/views/admin/dashboard.py | 11 +++++
6 files changed, 63 insertions(+), 28 deletions(-)
create mode 100644 bookwyrm/templates/settings/dashboard/works_chart.html
diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html
index cd0ddc842..445bf2992 100644
--- a/bookwyrm/templates/settings/dashboard/dashboard.html
+++ b/bookwyrm/templates/settings/dashboard/dashboard.html
@@ -102,6 +102,12 @@
+
+
{% trans "User signup activity" %}
+
+
+
+
{% trans "Status activity" %}
@@ -109,9 +115,9 @@
-
{% trans "User signup activity" %}
+
{% trans "Works created" %}
-
+
@@ -124,4 +130,5 @@
{% include 'settings/dashboard/user_chart.html' %}
{% include 'settings/dashboard/status_chart.html' %}
{% include 'settings/dashboard/registration_chart.html' %}
+{% include 'settings/dashboard/works_chart.html' %}
{% endblock %}
diff --git a/bookwyrm/templates/settings/dashboard/registration_chart.html b/bookwyrm/templates/settings/dashboard/registration_chart.html
index e98a0f18f..3b258fec8 100644
--- a/bookwyrm/templates/settings/dashboard/registration_chart.html
+++ b/bookwyrm/templates/settings/dashboard/registration_chart.html
@@ -8,8 +8,8 @@ var registerStats = new Chart(
labels: [{% for label in register_stats.labels %}"{{ label }}",{% endfor %}],
datasets: [{
label: '{% trans "Registrations" %}',
- backgroundColor: 'rgb(75, 192, 192)',
- borderColor: 'rgb(75, 192, 192)',
+ backgroundColor: 'hsl(171, 100%, 41%)',
+ borderColor: 'hsl(171, 100%, 41%)',
data: {{ register_stats.total }},
}]
},
diff --git a/bookwyrm/templates/settings/dashboard/status_chart.html b/bookwyrm/templates/settings/dashboard/status_chart.html
index 5e1045fce..a59036a51 100644
--- a/bookwyrm/templates/settings/dashboard/status_chart.html
+++ b/bookwyrm/templates/settings/dashboard/status_chart.html
@@ -9,8 +9,8 @@ var statusStats = new Chart(
labels: [{% for label in status_stats.labels %}"{{ label }}",{% endfor %}],
datasets: [{
label: '{% trans "Statuses posted" %}',
- backgroundColor: 'rgb(255, 99, 132)',
- borderColor: 'rgb(255, 99, 132)',
+ backgroundColor: 'hsl(141, 71%, 48%)',
+ borderColor: 'hsl(141, 71%, 48%)',
data: {{ status_stats.total }},
}]
},
diff --git a/bookwyrm/templates/settings/dashboard/user_chart.html b/bookwyrm/templates/settings/dashboard/user_chart.html
index 33be28f7e..a8d356bb8 100644
--- a/bookwyrm/templates/settings/dashboard/user_chart.html
+++ b/bookwyrm/templates/settings/dashboard/user_chart.html
@@ -1,29 +1,25 @@
{% load i18n %}
diff --git a/bookwyrm/templates/settings/dashboard/works_chart.html b/bookwyrm/templates/settings/dashboard/works_chart.html
new file mode 100644
index 000000000..c65014e98
--- /dev/null
+++ b/bookwyrm/templates/settings/dashboard/works_chart.html
@@ -0,0 +1,21 @@
+{% load i18n %}
+
+
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py
index 27edc3438..b1aedecf7 100644
--- a/bookwyrm/views/admin/dashboard.py
+++ b/bookwyrm/views/admin/dashboard.py
@@ -73,6 +73,16 @@ class Dashboard(View):
}
)
+ works_chart = Chart(
+ queryset=models.Work.objects,
+ queries = {
+ "total": lambda q, s, e: q.filter(
+ created_date__gt=s,
+ created_date__lte=e,
+ ).count()
+ }
+ )
+
data = {
"start": start.strftime("%Y-%m-%d"),
"end": end.strftime("%Y-%m-%d"),
@@ -90,6 +100,7 @@ class Dashboard(View):
"user_stats": user_chart.get_chart(start, end, interval),
"status_stats": status_chart.get_chart(start, end, interval),
"register_stats": register_chart.get_chart(start, end, interval),
+ "works_stats": works_chart.get_chart(start, end, interval),
}
return TemplateResponse(request, "settings/dashboard/dashboard.html", data)
From 2335945a501949c81f6a40c85216f0428a7889c3 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 11:16:02 -0700
Subject: [PATCH 10/11] Python formatting
---
bookwyrm/views/admin/dashboard.py | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py
index b1aedecf7..2766eeebb 100644
--- a/bookwyrm/views/admin/dashboard.py
+++ b/bookwyrm/views/admin/dashboard.py
@@ -46,41 +46,43 @@ class Dashboard(View):
"active": lambda q, s, e: q.filter(
Q(is_active=True) | Q(deactivation_date__gt=e),
created_date__lte=e,
- ).filter(
+ )
+ .filter(
last_active_date__gt=e - timedelta(days=31),
- ).count()
- }
+ )
+ .count(),
+ },
)
status_queryset = models.Status.objects.filter(user__local=True, deleted=False)
status_chart = Chart(
queryset=status_queryset,
- queries = {
+ queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
- }
+ },
)
register_chart = Chart(
queryset=user_queryset,
- queries = {
+ queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
- }
+ },
)
works_chart = Chart(
queryset=models.Work.objects,
- queries = {
+ queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
- }
+ },
)
data = {
@@ -106,14 +108,14 @@ class Dashboard(View):
class Chart:
- """ Data for a chart """
+ """Data for a chart"""
def __init__(self, queryset, queries: dict):
self.queryset = queryset
self.queries = queries
def get_chart(self, start, end, interval):
- """ load the data for the chart given a time scale and interval """
+ """load the data for the chart given a time scale and interval"""
interval_start = start
interval_end = interval_start + timedelta(days=interval)
From 636eca97cb121be6a454df9f1734b748c1565040 Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Mon, 4 Oct 2021 11:22:14 -0700
Subject: [PATCH 11/11] Better mobile display
---
bookwyrm/templates/settings/dashboard/dashboard.html | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html
index 445bf2992..f320028b7 100644
--- a/bookwyrm/templates/settings/dashboard/dashboard.html
+++ b/bookwyrm/templates/settings/dashboard/dashboard.html
@@ -9,26 +9,26 @@
{% block panel %}
-
-
+
+
{% trans "Total users" %}
{{ users|intcomma }}
-
+
{% trans "Active this month" %}
{{ active_users|intcomma }}
-
+
{% trans "Statuses" %}
{{ statuses|intcomma }}
-
+
{% trans "Works" %}
{{ works|intcomma }}
@@ -64,7 +64,7 @@
{% trans "Instance Activity" %}
-