From f364a72c8305ca07ac90f457370daeba32783b7f Mon Sep 17 00:00:00 2001 From: evilhero Date: Tue, 30 Jul 2013 00:57:37 -0400 Subject: [PATCH] IMP: Torrent Integration with CBT and KAT, IMP: RSS Feed Integration, IMP: Multiple Alternate Search Names, IMP: Newznab Provider Name Field, FIX:(#475) Metatagging not changing status, FIX:(#468) Covers not displaying in FF, FIX:(#469)(#459) NZB Search Scan Error, FIX: (#467) Annuals not found ... too many to list. --- bs4/builder/_lxml.py | 179 ----- cache/blankcover.jpg | Bin 2052 -> 0 bytes data/interfaces/default/artistredone.html | 623 ----------------- data/interfaces/default/comicdetails.html | 65 +- data/interfaces/default/config.html | 121 +++- data/interfaces/default/history.html | 6 +- .../default/images/torrent-icon.png | Bin 0 -> 209990 bytes data/interfaces/default/logs.html | 16 +- data/interfaces/default/readlist.html | 8 +- data/interfaces/default/upcoming.html | 16 +- mylar/PostProcessor.py | 23 +- mylar/__init__.py | 132 +++- mylar/cmtagmylar.py | 73 +- mylar/filechecker.py | 117 ++-- mylar/findcomicfeed.py | 2 +- mylar/ftpsshup.py | 48 ++ mylar/helpers.py | 53 +- mylar/importer.py | 12 +- mylar/rsscheck.py | 519 ++++++++++++++ mylar/search.py | 651 ++++++++++++------ mylar/updater.py | 92 ++- mylar/webserve.py | 152 +++- mylar/weeklypull.py | 17 +- 23 files changed, 1696 insertions(+), 1229 deletions(-) delete mode 100644 bs4/builder/_lxml.py delete mode 100644 cache/blankcover.jpg delete mode 100755 data/interfaces/default/artistredone.html create mode 100755 data/interfaces/default/images/torrent-icon.png create mode 100644 mylar/ftpsshup.py create mode 100755 mylar/rsscheck.py diff --git a/bs4/builder/_lxml.py b/bs4/builder/_lxml.py deleted file mode 100644 index c78fdff6..00000000 --- a/bs4/builder/_lxml.py +++ /dev/null @@ -1,179 +0,0 @@ -__all__ = [ - 'LXMLTreeBuilderForXML', - 'LXMLTreeBuilder', - ] - -from StringIO import StringIO -import collections -from lxml import etree -from bs4.element import Comment, Doctype, NamespacedAttribute -from bs4.builder import ( - FAST, - HTML, - HTMLTreeBuilder, - PERMISSIVE, - TreeBuilder, - XML) -from bs4.dammit import UnicodeDammit - -LXML = 'lxml' - -class LXMLTreeBuilderForXML(TreeBuilder): - DEFAULT_PARSER_CLASS = etree.XMLParser - - is_xml = True - - # Well, it's permissive by XML parser standards. - features = [LXML, XML, FAST, PERMISSIVE] - - CHUNK_SIZE = 512 - - @property - def default_parser(self): - # This can either return a parser object or a class, which - # will be instantiated with default arguments. - return etree.XMLParser(target=self, strip_cdata=False, recover=True) - - def __init__(self, parser=None, empty_element_tags=None): - if empty_element_tags is not None: - self.empty_element_tags = set(empty_element_tags) - if parser is None: - # Use the default parser. - parser = self.default_parser - if isinstance(parser, collections.Callable): - # Instantiate the parser with default arguments - parser = parser(target=self, strip_cdata=False) - self.parser = parser - self.soup = None - self.nsmaps = None - - def _getNsTag(self, tag): - # Split the namespace URL out of a fully-qualified lxml tag - # name. Copied from lxml's src/lxml/sax.py. - if tag[0] == '{': - return tuple(tag[1:].split('}', 1)) - else: - return (None, tag) - - def prepare_markup(self, markup, user_specified_encoding=None, - document_declared_encoding=None): - """ - :return: A 3-tuple (markup, original encoding, encoding - declared within markup). - """ - if isinstance(markup, unicode): - return markup, None, None, False - - try_encodings = [user_specified_encoding, document_declared_encoding] - dammit = UnicodeDammit(markup, try_encodings, is_html=True) - return (dammit.markup, dammit.original_encoding, - dammit.declared_html_encoding, - dammit.contains_replacement_characters) - - def feed(self, markup): - if isinstance(markup, basestring): - markup = StringIO(markup) - # Call feed() at least once, even if the markup is empty, - # or the parser won't be initialized. - data = markup.read(self.CHUNK_SIZE) - self.parser.feed(data) - while data != '': - # Now call feed() on the rest of the data, chunk by chunk. - data = markup.read(self.CHUNK_SIZE) - if data != '': - self.parser.feed(data) - self.parser.close() - - def close(self): - self.nsmaps = None - - def start(self, name, attrs, nsmap={}): - # Make sure attrs is a mutable dict--lxml may send an immutable dictproxy. - attrs = dict(attrs) - - nsprefix = None - # Invert each namespace map as it comes in. - if len(nsmap) == 0 and self.nsmaps != None: - # There are no new namespaces for this tag, but namespaces - # are in play, so we need a separate tag stack to know - # when they end. - self.nsmaps.append(None) - elif len(nsmap) > 0: - # A new namespace mapping has come into play. - if self.nsmaps is None: - self.nsmaps = [] - inverted_nsmap = dict((value, key) for key, value in nsmap.items()) - self.nsmaps.append(inverted_nsmap) - # Also treat the namespace mapping as a set of attributes on the - # tag, so we can recreate it later. - attrs = attrs.copy() - for prefix, namespace in nsmap.items(): - attribute = NamespacedAttribute( - "xmlns", prefix, "http://www.w3.org/2000/xmlns/") - attrs[attribute] = namespace - namespace, name = self._getNsTag(name) - if namespace is not None: - for inverted_nsmap in reversed(self.nsmaps): - if inverted_nsmap is not None and namespace in inverted_nsmap: - nsprefix = inverted_nsmap[namespace] - break - self.soup.handle_starttag(name, namespace, nsprefix, attrs) - - def end(self, name): - self.soup.endData() - completed_tag = self.soup.tagStack[-1] - namespace, name = self._getNsTag(name) - nsprefix = None - if namespace is not None: - for inverted_nsmap in reversed(self.nsmaps): - if inverted_nsmap is not None and namespace in inverted_nsmap: - nsprefix = inverted_nsmap[namespace] - break - self.soup.handle_endtag(name, nsprefix) - if self.nsmaps != None: - # This tag, or one of its parents, introduced a namespace - # mapping, so pop it off the stack. - self.nsmaps.pop() - if len(self.nsmaps) == 0: - # Namespaces are no longer in play, so don't bother keeping - # track of the namespace stack. - self.nsmaps = None - - def pi(self, target, data): - pass - - def data(self, content): - self.soup.handle_data(content) - - def doctype(self, name, pubid, system): - self.soup.endData() - doctype = Doctype.for_name_and_ids(name, pubid, system) - self.soup.object_was_parsed(doctype) - - def comment(self, content): - "Handle comments as Comment objects." - self.soup.endData() - self.soup.handle_data(content) - self.soup.endData(Comment) - - def test_fragment_to_document(self, fragment): - """See `TreeBuilder`.""" - return u'\n%s' % fragment - - -class LXMLTreeBuilder(HTMLTreeBuilder, LXMLTreeBuilderForXML): - - features = [LXML, HTML, FAST, PERMISSIVE] - is_xml = False - - @property - def default_parser(self): - return etree.HTMLParser - - def feed(self, markup): - self.parser.feed(markup) - self.parser.close() - - def test_fragment_to_document(self, fragment): - """See `TreeBuilder`.""" - return u'%s' % fragment diff --git a/cache/blankcover.jpg b/cache/blankcover.jpg deleted file mode 100644 index 43472a432188906dd186f286867acecfe9319f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2052 zcmb7EYdD)}8h*bBiPRx94sB>O6h&KEB8PqJQdLXYn$fvXm4-OY&@#>;s6+M(?R9m2?)&|C-|u6+jRG5c~ki5O4zWaws%PP9BXyV=(gj6xEd#6%-WlI5n)gjy92~qfH>_8Je5u z>5~iygk!eHNEQ?;D=S@NduMw~C-ak56loC%gTW{&C>~T+K1ex2I70cqm*hE6K||`G zQ3fIcgbF010!camUMf`vlIs1mAcPE3P8J0x-LS9+83craSZe761up&oK3!U)ItPCp}I_)+(@_t%mWMyzE z-lPJL2YAQF$kfO1jyD0Ncq6F(F}7mk;G0}_c%k4S_4$jJ53;^vUkhM!+4j6Rf|D*A z(wyFQ+pQKTpi?{NYsQrdbwC9G2*Z>dgdrl*5MY1~P&}a3fBLU6eeyJ!nvgZ$#Z0Ht zkB3uz*PW>j0I2$6fe%s^0w(cYqhZxcI$7y|?62lC@M$#0QA z-chPz2xz?;}XsDlViQuUhvu>TZ1`z_}oi zh47T%RDGcz7lH$4ku`ZU$2JSv8fyu!ht@*UFZE$Eh}Cd^5K=k2OYug6ESE3u&tE;a z%^%|rhI|C>Lra~W9&L1hkZR!8M|1?2uVD?TcGWb^cgc0~4zWjhT6oMUHJp#M36L7( z2zLjI)1p_IOTg6^>#ui$XFq$1oC_Tv;i}J0`g1Q_!1cx!7jHJn4Yi~O1s~qyC95ZS zwZ>YS;e5XUMEKfuGK>%@Ft_}1Mg2)$ydCNXt{48dp`rLEo2CmzZFkOIs0T z)`wTGh`04ztX;Q;y3PuXPDZ~oP`@PnzQxUW<{HJ2cU3ouQ`*3+OkO+7jN1M~9MRGp zmh;esdUZ9%Z_2Yj>M}8Glf`+YNo9r8&-ab=N3e-?l_Y&~ab9J7DC-*uXt2??H%1*7 z23U*_Xq=!;MJ3YRNR1j45hpph{Mz`d^!ef0ePt=xp#xO7H<2bE9@z57eu1wB032{6 z`+)tA;UPfADTWjU)^j?K*L*FjzF6lh>Y(}l60<<+UlZGIwNjQ#!kRc22mN^e*x z{o`wq-LIm2`z@sljX~>=bT@>Y<@izkZJRKDVy$&i;ACMk?^X7c$Y^RRIbwQllT2By z|1CN7cR$}j*2Nxks&mxLMm6_c*Sz1*)AYX3fheX~?<=9T1pIU8Zcy>m_L&Ex$vKx@ zG&E`jYe&b12XY7M67DTVI_N+?KGGY9V8xI@(nd;APHWT)^3q8^e{o%>c3CaY)6;WK zYgnWlY8SioWa!$frGRz*THRPwo@=M_>^biImrX%GOzrF>2S==Y@P0Bqn#R~aKWz~* zn44+YWHQ{;J@etsC1TlDcWcJaJv;gRVhM2ny987$ClOPmV&N%ydRld{c|>ott8a$k z(R0f=$)mAf0`9a6JvuK>mz;Z;%NZ;v%XInK^7U6G5j=dyTyGz1B00aDDX_2RO(X;w zUk@L#FrRBOF3)1yy`YLOhcs+F9qhTHu|3Y&^4}UM5e{2&vqSMlJpv9fT#)mAbj@hC z3N=_AfV|mk^Y7Kj3tY$jeg4N0cIK#d;F;Ao##%w*&=PieR;uy zu@}`eWu926p6=>dkBQ4#mVh(g75~1`s>Hx*n%qpPI=dM%C8EQfJHd<(67QCg@!h%~ zM(SsjExune_ggMzInP-NGTT|5AW8q5XFb)4RyGlYqw$o6aDoy;6Iv-^C6MpKSf=}@ z7yY6bY`iFTRP(RsExDy@U$Qzt`?RjJ*mL2QTV5H#P+&ppf%ld7ODT5GQ1|!& WV)kU|O -<%! - import os - from mylar import db - import mylar -%> - -<%def name="headerIncludes()"> -
-
- Refresh Comic - Delete Comic - %if mylar.RENAME_FILES: - Rename Files - %endif - Recheck Files - %if comic['Status'] == 'Paused': - Resume Comic - %else: - Pause Comic - %endif - -
-
- -<%def name="body()"> - -
-

- %if comic['Status'] == 'Loading': - loading - %endif -
- - ${comic['ComicName']} (${comic['ComicYear']}) - %if comic['Status'] == 'Loading': -

(Comic information is currently being loaded)

- %endif -
-

-
- - -
- -
- -
- -
- - - - - - - -
-
-
- -
-
-
- %if comic['ComicPublisher'] == 'DC Comics': - DC - %elif comic['ComicPublisher'] == 'Marvel': - Marvel - %elif comic['ComicPublisher'] == 'Image': - Image - %elif comic['ComicPublisher'] == 'Dark Horse Comics' or comic['ComicPublisher'] == 'Dark Horse': - Darkhorse - %elif comic['ComicPublisher'] == 'IDW Publishing': - IDW - %elif comic['ComicPublisher'] == 'Icon': - Icon - %elif comic['ComicPublisher'] == 'Red5': - Red5 - %elif comic['ComicPublisher'] == 'Vertigo': - Vertigo - %elif comic['ComicPublisher'] == 'ShadowLine': - Shadowline - %elif comic['ComicPublisher'] == 'Archie Comics': - Archie - %elif comic['ComicPublisher'] == 'Oni Press': - Oni Press - %elif comic['ComicPublisher'] == 'Tokyopop': - Tokyopop - %elif comic['ComicPublisher'] == 'Midtown Comics': - Midtown - %elif comic['ComicPublisher'] == 'Boom! Studios': - Boom! - %elif comic['ComicPublisher'] == 'Skybound': - Skybound - %elif comic['ComicPublisher'] == 'Vertigo': - Dynamite - %elif comic['ComicPublisher'] == 'Top Cow': - Top Cow - %elif comic['ComicPublisher'] == 'Dynamite Entertainment': - Dynamite - %elif comic['ComicPublisher'] == 'Cartoon Books': - Cartoon Books - %endif -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- -
-
- -
-
-
- - - - - -
-
-
- -
-
-
- %if comic['ComicPublisher'] == 'DC Comics': - DC - %elif comic['ComicPublisher'] == 'Marvel': - Marvel - %elif comic['ComicPublisher'] == 'Image': - Image - %elif comic['ComicPublisher'] == 'Dark Horse Comics': - Darkhorse - %elif comic['ComicPublisher'] == 'IDW Publishing': - IDW - %endif -
-
- -
-
- -
-
- -
-
- -
-
- -
- <% - if comic['UseFuzzy'] == "0" or comic['UseFuzzy'] is None: - fuzzy = "None" - fuzzy_year = "0" - elif comic['UseFuzzy'] == "1": - fuzzy = "Remove Year" - fuzzy_year = "1" - elif comic['UseFuzzy'] == "2": - fuzzy = "Fuzzy Year" - fuzzy_year = "2" - - %> - -
- -
- -
-
-
-
- - - - - -
-
-
- -
-
-
- %if comic['ComicPublisher'] == 'DC Comics': - DC - %elif comic['ComicPublisher'] == 'Marvel': - Marvel - %elif comic['ComicPublisher'] == 'Image': - Image - %elif comic['ComicPublisher'] == 'Dark Horse Comics': - Darkhorse - %elif comic['ComicPublisher'] == 'IDW Publishing': - IDW - %endif - -
- -


-
-
- -
-
the directory where all the comics are located for this particular comic
-
-
- -
-
Alternate comic names to be searched in case naming is different (ie. Hack/Slash = hack-slash)
-
- -
-
-
- -
- - - -
- - -
-
-
-
-
- - %if annuals: - -
-
    -
  • I
  • -
  • A
  • -
  • S
  • -
- %endif - - - -
-
- - - - -
-
- - %if annuals: -
- %endif -
-
-
Mark selected issues as - - selected issues - - -
- - - - - - - - - - - - - - - %for issue in issues: - <% - if issue['Status'] == 'Skipped': - grade = 'Z' - elif issue['Status'] == 'Wanted': - grade = 'X' - elif issue['Status'] == 'Snatched': - grade = 'C' - elif issue['Status'] == 'Downloaded': - grade = 'A' - elif issue['Status'] == 'Archived': - grade = 'A' - else: - grade = 'A' - %> - - - - - - - - - - - %endfor - -
IntIssNumNumberNameDateStatusOptions
${issue['Int_IssueNumber']}${issue['Issue_Number']}${issue['IssueName']}${issue['IssueDate']}${issue['Status']} - %if issue['Status'] == 'Downloaded' or issue['Status'] == 'Archived': - <%Csize = mylar.helpers.human_size(issue['ComicSize'])%> - - %endif - - %if issue['Status'] == 'Skipped': - - %elif (issue['Status'] == 'Wanted'): - - %elif (issue['Status'] == 'Snatched'): - - - %elif (issue['Status'] == 'Downloaded'): - - %if issue['inCacheDIR']: - <% - try: - with open(os.path.join(mylar.CACHE_DIR,issue['Location'])) as f: - linky = issue['Location'] - except IOError as e: - linky = None - %> - %if linky: - - %else: - - %endif - %else: - - %endif - - %else: - - - %endif - -
-
-
- %if annuals: -
-
- - - - - - - - - - - - - - - - %for annual in annuals: - <% - if annual['Status'] == 'Skipped': - grade = 'Z' - elif annual['Status'] == 'Wanted': - grade = 'X' - elif annual['Status'] == 'Snatched': - grade = 'C' - elif annual['Status'] == 'Downloaded': - grade = 'A' - elif annual['Status'] == 'Archived': - grade = 'A' - else: - grade = 'A' - %> - - - - - - - - - - - - %endfor - -
NumberNameDateStatusOptions
${annual['Issue_Number']}${annual['IssueName']}${annual['IssueDate']}${annual['Status']} - %if annual['Status'] == 'Downloaded' or annual['Status'] == 'Archived': - <%Csize = mylar.helpers.human_size(annual['ComicSize'])%> - - %endif - - %if annual['Status'] == 'Skipped': - - %elif (annual['Status'] == 'Wanted'): - - %elif (annual['Status'] == 'Snatched'): - - %elif (annual['Status'] == 'Read'): - - %else: - - - %endif - -
-
-
- %endif - - -<%def name="headIncludes()"> - - - %if comic['Status'] == 'Loading': - - %endif - - - -<%def name="javascriptIncludes()"> - - - - - - - diff --git a/data/interfaces/default/comicdetails.html b/data/interfaces/default/comicdetails.html index 5fcf8134..7d3930ef 100644 --- a/data/interfaces/default/comicdetails.html +++ b/data/interfaces/default/comicdetails.html @@ -180,7 +180,25 @@
- +
<% if comic['UseFuzzy'] == "0" or comic['UseFuzzy'] is None: @@ -238,13 +256,14 @@
-
+ +
Alternate comic names to be searched in case naming is different (ie. Hack/Slash = hack-slash)
+

-
@@ -267,6 +286,7 @@ +
@@ -314,6 +334,8 @@ grade = 'A' elif issue['Status'] == 'Archived': grade = 'A' + elif issue['Status'] == 'Ignored': + grade = 'A' else: grade = 'A' %> @@ -331,7 +353,7 @@ %endif - %if issue['Status'] == 'Skipped': + %if issue['Status'] == 'Skipped' or issue['Status'] == 'Ignored': %elif (issue['Status'] == 'Wanted'): @@ -358,8 +380,8 @@ %endif %else: - - + + %endif @@ -367,13 +389,13 @@ %endfor - + %if annuals:

Annuals

-
Mark selected issues as +
Mark selected annuals as - selected issues + selected annuals
@@ -446,19 +468,12 @@ %endif - %if annual['Status'] == 'Skipped': - - %elif (annual['Status'] == 'Wanted'): + <% amode = 'want_ann' %> + - %elif (annual['Status'] == 'Snatched'): - - %elif (annual['Status'] == 'Read'): - - %else: - - - %endif - + + + @@ -467,14 +482,14 @@ %endif - + <%def name="headIncludes()"> %if comic['Status'] == 'Loading': - + %endif @@ -637,8 +652,8 @@ } $(document).ready(function() { - $('#issue_table').dataTable(); - $('#annual_table').dataTable(); + $("issue_table").dataTable(); + $("annual_table").dataTable(); initThisPage(); }); diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 6c3a26d1..30ba215f 100755 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -66,7 +66,7 @@
-
Coming Soon...
+
@@ -215,7 +215,7 @@
-
+
Where your SAB downloads go... (optional) @@ -307,6 +307,51 @@
+ Torrents +
+
+ +
+
+
+ +
+
+
+ +
+ Local Folder your torrent client watches +
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ Folder path your torrent seedbox client watches +
+
+
+
+ @@ -316,10 +361,18 @@ - + %endfor diff --git a/data/interfaces/default/images/torrent-icon.png b/data/interfaces/default/images/torrent-icon.png new file mode 100755 index 0000000000000000000000000000000000000000..594fd0206c4c29bc39f319268a989aaa86c4e247 GIT binary patch literal 209990 zcmeEtRaaYW7j1%5C|Zg%IE7-xN}J&B#T{B)ibHUBDee~B9ZG>xytoB-*Wm7Yc)u~u zZ#Xw+-(=tHjIq`;pCxn66{aXJ`T7;vD*yoST3Sj>82~_fc|`(XpuPNDxK7>y06_L1 zqN0k@qM}ra4z{L0tV{p^S6E_nn@p$Tn~=75;@vsw80)Kc3`&YtQyme~IzOp2%S7WU zq(u|Q=@xaLFQ`FFJb(V&qsT}32dop`p#4-q55edtxkzt4->?GC&!C zk8Ws!r6yYANA$vU3L&XcXsLV=oni%HdppHgo6o>%7+ZaM)MByrbjNl=3&Xm5>(Jpo z3NSP=nT8pIZE7m(m67e4?jlLWzfsDG?y^$VQl{YmR;@VJ!O!(38$eurTCRpu05v9> zKY4th8)rPSsg$qde16U?_k#%G&J(H#PfGg;o?Retq?UE?m({T7kJ8;1kCA1MOG?X^ zKW#ZqOz()#f0VA;n`*j-dB6n_8FkYQt#xll$NvBG|I7oY*Fdiv-0Zx(4KBl5mxQ#o zg{qN@WuFhO=|1P<*AJx23u9xa;-Nlh>hK*3`>KZXzxK9v%T7&8YdqK~^t(!1W(XiiW%V!H;t-9@kM* ziR4Y{&J`63{~X`DX3b1HzfL~T)ZuNe|LcC`=;XBG$T`PPu0E}yKI80bjzKLKg6E%y zr)y_Jpf0j4*Wua zX82uM@)qUtqLGtlp*x~y=WRd(OptATJRUiXj-O8(ybc=?AczC}iQnV;c(KK$_lUe{ znqVZlva(Y57Zec%Eu2VvoJgEnif1p6efQ5e#n8m*brj%Z&8L0I>NEwkGIA3S!el|X zm4WmXQ7}+U=qF|ey0P6OI}H_=5P-`s3?IQ|1^>*^bNgb7{K)4oQ6s&>_wpHFx0#aR zx#5qv4djBiqdonE4Duk49Y3S2r%6_qrz_j$EgS&mItI)05-0i+~fm*pWTk}Rl0h57>71M=k@}WX6d-_?cLcL^rKr8$=2hGT@_pkkJTq$ z+qT1~=*RVu=bn3jSSanNcLw9sOISF)7W)rFPe+?V8Brks zrg)8KTaUge5<_NO5%y6ey|>_=jTihhBPRPdt_4m`0$i4TR$3@;SJ4ICJ1HOAe7puv zH+sz&6f!|d8388s*|jL-(ULo$GtJW(gnh=W=)GKND?XTf=%t1z5lh?-YB$l^H9MfU@5dASfbKF@7x+Dda z?`oHlZzmWY1C@Xey-P3pOyPdhVf5}@(edB=BVK`%wP??a=r8i!ycB<~b3#_mk{Xs= z*1N(?iuAQ~UXI2d?LT9TJXln2B@nn(4@t?Oma{Wvwz*of>$!WJ1GgT(NA%3!t*!U| zElpRI3Wa4-j0PA$IKHxsR2aU$K6Qx*=&3##l6Ff|OYI5MT$j%WVk@H6hT;WL>o4Ip zpodtYwZbHwK5OsGPFkR|I8o{R;(TAoMMdLEyf+_%tON+Hv3Cznkn95ctj;3idYxeR)1Re&}FrSaf(bMQW~swnVz)I+Xho-J-dzipD8h*O@aLk5ATU&AvS* z4C=X#i4(WlJ!^%q&DBAVb5=84HaWhfQbj>Ghx(|7M>IJ8Zp{tQMl!vW-aC~>xQoyU1_8GTpXaV#Tc3p@o4d^xTd#dy%C6Ko zzo@8Qloy1aYWj-bVKqJ^w;Z^kXI&jwR)MR1j=3dqD80t!(4)WCJeP~|2DpU&Krw4~ z>)+_rjEotb6|t#J>X*K-?ir7$_=RMFV(FbJEN^aGBmswvp#>VeI@S%_Yr&=YTieW6 z8p)s?nwKo!cm>oPz_hCUWM(nc&`i$SQegjj@|v3d(vKvSP?>B>I8^E-98bn_PLm&Fiq=WH%y@@UMLxUw}|LO5wL+_ct%KgcNSkL<~ z)2k`7#&)Hn%%$>Bd#TRSCCpf5KxRr-RarTKfFXWgn!{X~L9 zQ!2*0Qc)FWW*kxbIK^@|hy*+BR_F_A%S}VwP!JI$lKG$f!(^A+Lg~4kXmW+a@5wot zEMp|7%>1u$;=?56FgH>z@9gY9fFMJ?5cy2^ok?U|a*yYhUW%K+`=jQK0NaN!J+J-U ziJ~vSp|J@R@@U}yj1D%*69lAq_wIkU-c{{j~ z0N2LG@40VzzGlJag~nePgs|}~EC0GdmBx?*@zAghkPv8rc!8ybY4_7#+y5>(7r0cT z@##M{P4CRaJqB;vHn0RYdrpp9E`)D}!LFz^<3MkFjQT%*9=lJP8PLfOtOld+9oW5P zpew*Pg6*!P_d${^Cy(UebHw$+Nj=ns*#053RNK1s_TQ)Hncg(d6pCXHZNDSga9y9R z@ep*q=67kn&+s{~TzQ`Q^1K{E71i#LYT$yxL&3d+Bh;G*9DMU^*MW*YU3DABkoDM% z5Zovr)^k0*M8Lc@e|>AZIy{e(!SRZKZi>aYKd|7lNS9=gWCoko!=OfvK=TqkG)R9Z zAqLz7+u$c2nk(^7p=#%YGPG3U1BRTy`6;%TnY7K8>ve3BT1D?jOTATbXTS}%y!clo z)neM3Nx^Ii!B6vg;C}^PGl$yOexW~WYwhUv@KULiO5Z0?OF_H9h5}hXuCk`W^zqz= zdg*q_&~F2z9p4<*iB5kKW$KklbFLW(gb{)nV0>OL7T+H|&PGx`k5V?DA5z}Ozq4^Y zUbtXFFe zkEK=R`TqJz**m>%#QQuRbz>hiwG0IGl`QEfuFbqBplz!gl8@@o=zy#SNqIL0`I3(~ zx1jD>W|f4rI}G@BEbcJ9#YG(ooU;n%80LsdPZ==j{`ar*QnNu z>7V{*x@h_WE`T0DFZiTV<#p$V&^sCGl#FV;XavRyW8T~+W@{HhA{W8rD zPB zrwyUk%-~6SGfF4NQHal=zz;iWdtSa?^j@&`IXhKYeh~DzHGAG@0uCvvpiJ8p=WXBz zy!1|d%A?~C$XzE2&zB>Q;rncDXM4#Yenj*Bw8jkX(PE7b(Y;|gRGtcfZ=`OqGWme_ zbD7spp61R-LXIg^2X94M;fY<2J&-Zj;1xn7?5P4)H98*@Ybyt9`5nWnmp|4Zv0)vx zQsPI9y!X3NVSpfmP!ry5r8vl$&|*bg{E_)_;SIXA)2n)*ZPW2|&CO7**vCpCBCh&< zdZTd6O+JUWW=w%O>|bD{jKlV4lbA!>TwNb30+Y=MXU%vKChc)a_(;UdXY{(KJbyI6qUh46wvs^sbI^0Iqd=%X3wqDrt@4iCOxkPeq z9h4Krk`!5aC#?MXPc>6mEe|qnkA3i*Co)G==#R=SAfrci<8xt~ubTU2!mA+KAsM_Y z^l{}mtu}OrS+JMkMy1E`&FJtKpNF=m-KyPwUPYxo;GkI?Kev z1f_eYWmV%{n1=UdM?gsH*-1_wqN1w8045pOLAxE8O@3j@K@I*9x6vXN&1jiPNoqgD zZ5u_0Pmk&gPzVU^{Xi9nsb0t|&PL^Q80Xp$4E#R$}#k{#lup03tcCY zQZ!;^y)i{4?;9$$h5Ksf$*0MhQ2$F6>n~EBV8Xfx=~_tQ zCu~|o8XEhzKxp~G^x>=w62y;7%_gWef@Ya7$bM05yjbrOawRsag}7fOBr1W>_~I8c z7k)lbjp%@q3{gfWIBRVg{pfD;uwm&`&!+LVUeI&mozGUwY#PN*lu$1*`G29H8!hiP zeC@gai`NX+2=DVt{*YCzq`97>A;qwrB8mU> zH5jOP*$ic}nvlw94sbyZHX!Q2rFv!ey?C8Ol7j@VQ;5uvm!QslKsWa~2u-;7)~rkz zouzlFy6Z}tacjc5v1=sv0X=3wQ=f5cP&;#nYTj=Z*$|XIMHiV8eopw2f$6rHy%;q4b*s# zUU&P74vvR%&E6qxqLAu@8!iq7+rQ;@4?9S0;M)y{#w6>NR0I+m8V(;W2y&(S+00+z zeR`ce9Po!@`z}@OqTaauD^*HEVR<8eA*(wQO9A@O!*Z?@Po zrjgu$qg1{^TxD_ux-=I(8m&pY%o|G$VR9uog8m}#%tbrsU9Czz0RT{BlCJzS#W50d z8CQzYB3Yt{h`NU+2HVP?8Hz2R;eK;N?y~IN*(>0@;p5$j`!wz&>V#5WB=k}~w66YF zJ`j^ttYv+N4sUt1J`u6Gt#Qxjp0kGFP_&qi9PwMu6U!G3nQY2oEE|}JgZzi*KyU~n z=3q^K?Tj@nO&N~42}?Sxpa~2!M=dQ8x74pVWcw04lbFMsuj&*@((q||?ep{3;boo9 z)Uul4K}n^&b<{Oo(OrdL;3|rQlayVsb#k7K(m+;8fPU?vzqtauz^1A0->RIFz#lR< zJ8KKNg=}4PG+7;kr4Vf1Qm6Y=Qu_$)uQ_Ni%!uZ#l4UOkx0fZDa`kl6X~x7d;v;lxMdgu?I^|zjK|?)#3tJ37F={8m=K`Y zR|1&gRf8fbfCXbjyHCIipFVf)n^p-uvF#%Y9r_`@zbMEI>%or$wSsziK>8C-`&;A{ z9)Q^>M!WTdSYLfzY}>*mWsFR4`O@Rirv(Tvm~MMLj^lTK^!KU+36%^$ zD@9}_(d;-;1);=zC26RA@bH|pl~tyQ{P@#c@as9hR0D=whb*__aDnzFMP)$;g+DZ- zu;DLXY+Ek3T^3z8zP6qA+CC08v^z?pI*NyxVIcPcr(*^U#&6qCWVDnUH5s};-DK( z@=a1U2f86>I21V(6x=~f8}>AfHFni2Tff|Rh<+Km zF$O#4#LRAVGZ5IkTs#Pn8V8S#{N{d3do*caLHe30+06bodq6Fjt?m2laI@XjR~rBT zM`Y**cKZ42i1SF1%NZz6_bMSU3N2=04~UoIyUJ%Z$wlQ39E^hTIC(a2Tq!)>e$Bd> zJbsu@_t|e-abBp2$Lr81#&Y&t{x3(35D%Sr08{|Xg121H>vu&0TR&DDH&4dQ4i;<7 zEOMI?XfSX%IQlq(4SZd2q(gdAcIg0{NbOpBd2xhjz$hgDTo&8{$nNLEN$PJ&D*2ayC`Jdw0H1>E0v)AHi+3t9`g6~G8PkfDxBSmCM z*Zs#=WJpKwUXn1+0KlqZ3t_5L+g=ejvg5u0=T3JB+XNkF<4We4- z6PozK4neUJicz}J{NvoivtvoWHF~WxU+9E0@Y$lg1nedxkG}!#+?`-xFLX0_Wnm&V z&1_g(DS-Rl0z3F(q#06Sq|3qzi z!Ihivf4G`q$KeK$I3LW`T$TDbKE{84SVugUy)Y{mTK88Jv$46GRbeEI1I4W`E1#3f94VrQ>ynuO#At|9MBDFUwxto9Wnns%rM~F zybM`|XK_RY##244q(X(rBJFL*bn*7}{-h8gcIGl)m^}cWz++6@gi@ zzh8T*x865B?jWyWB#67xo+n( zK9E1MB^M0VC4`6dj-6DU9hZhA3L`J%_se^MMpMImFBgE^h=qr&9)9-l?PigN&u57#T*%v}6S>+X?u_TkU%S z5ZIJR6ax0oj}6Q2`;$4<2*|HButIjT4F%2`@f%Y`_b z>(gL#rpHBM2u`L8oE@d>!_t&GJ>k$cbQrjQSnOE+Ld)kUC18~KUsHt;0C^D{HzkvX zmho>>O0(WeY=eN3G!M-0eF5#GOdnG>i{QdefMRx>%UMP2OT#5!rlIgP`%(qKItlfA zi$;>N?v>_J=c2Q}6oMs+tPJ2HY*d-f6&gEavl4HvyB790gA(qH!7ezA)`DltG8n`S z6)l)akvF;K%2ydG5)l@#iWxt0Vk3hUClsVam{*>~hp4bR;d*m{P7-wP)oH9s!R z%1?^Fyky9vaRyRylI-o^`_2y0UEt21ZM2?0esfmHPS`oycXQ+XX+zWvF{U&rCo#Yz zr7_a+F?$dK?EL(#Vdbn};j!1Hb>Hjx_RDkhvjbNt?dSv&d6v_EEJ|&d`sx=g9i4^K ziMA8|s@C;0=GNOqTH+Z)(J zm~d2VZ=#MWsZQecoAp0|G|I|`ngEAEh4dfy%Nn16dC^u>Qg3W5=HV8SKLuIwV? z;k3Px{4Pa-v9g#^CX8mv0S*t!YRJM1jl6jMbnUZ)+;%%5cvbeiJ6WPqL?zNuiMw-C z{vWBD#Y(ay2&_J%6@0p5YrHDa@LCZk*7aVx+lyLlxu}lj=m-Idp7gniMc^B$a{m?h z&58=h7IUX|l`B%|`h$sQfWdt73An1JSP!dez+mn}L@5noT$-rN)`|_j>1P$$EDO2*E>M%IBN1w!89{kSh#pHr!1TLi$b=Dv1av zQLyxDPa?@5z5HiVjQ`w1cG=rey^6W=p;=f`(hmEZ$?3;^dQnmnsO1s`1>Wze$(vu; zx2@uM2_BmxF8!aS=#jvO*)7QPXfNfsM<1Eedz07xs@96un5;{vQ2R4uxUVX% zE9J$tuiZlz^7V@2grv{$$kV|$+b19Id)6!w1uRF;q|uie#Ro%%|M|U!-miP!wo4zk z+qxNnLteOm>m~su8us`5(%J~q#QOd6o=mEVo9wUOFeY|=-$-^P)WH;*9t-e&JK44T zTt542n0DzLJ{p!6HChbrD;IQXF=`+JlcFL1@uW`Vc{9bQgV`BFeRF{ z9a5N5Jb!`{Of=1VYFQ?Y@atH~){+?QvL$kkLh;ZH6j)xNYx6XJd(EMpy3qV(@1CT4 zO{-D?P#R0o8%mOl^Nye~j#ljJgjFNtCvpsN{Zvc1OlAY7X`{sLt{jr+6!GK`pd_iY z#8)B6Icn0L?l7ZW$|B+Y->Um-ft{8g#u4-aeTg!_AFY$0!+w44{P#8=Z1_3L$msly zGKhn||2Ure?XN~OIxe)$rxRI5qA|jD$mW~1PG5W2TI>DM!^^zOVWX<;HreOg#kT2i z)_zh#B;)nYjYrPQMfai9oP6m%AJ@Kk_ChN?rfc<}PmRPauGU@+%t-ujDVD8oqIlFq zF+VwK)yq=-sIf_U@y~BDj*GKM!5HzMW@W;32@E z;8c`W5b91YkdEOYoMxj!goaRh1B&Fc;(};JPLLf;!N*&z>nw8WB_OJ=#CG^}?oPQG zJovSd6B{oL>XqcN`%IJ1A;M?-*^~F}1k!)r;|(pEAdUzER0+2oZDy@>jN)Dm+U;p}g3vR=4XVN0a4Vr* zUEW`Rz4&c|w`NSBd2?eVHlGfJx46qwBfMFJaF&(Ae22HFmZmjvZ)?5lD;}MDrwi#d zqvKN(bF`ZAt?sgCMLvFNl9REbr~DTcA`}T#jtVF3_?E?#M!ZXc{*Rl$zG_YfK>%=Pk`phTO7HQ{d9 zFaC!qUm(D(>%*<#AY$K6`|B5DuDPjG^HOxW*9KF74@m#wY`?#)pR1o6Cva#M#W=}y z$iYd>*ZLtb}@3@H1XWrG<9k*UuVWomd|qqGnppviP3e*d9u-;4PcV z2)^7`l^8-8$p7&0nm2>FkSBIg;Jo>K@ekl%uZkRU8X}(@Kepe8T`3UnCDs1cc>fiX zL@JMy5m=5?y&5pSVfc{2fZZW0kdlWJ!GR`Bj_1*1%S93@yj7e35cBDdh*n)Ql>V1V zfxTKw@Q}n8Gh?EyI?({J4>O#|x|*2NeH!CL$~dI{k^|7MlAGJ-jSw3SndTvLE9uDD znv;JT@Q4JA?1~7ChLu`f6_1u?i4T*m_u6Gx`f#beu4;GptCrW;ObcJ`u!1jMn=c^G zD2wCcbM8CQmkejg)6;Nn<-d>b!JBfTcId0_|Cy^$JuYGNndx08SxLH7El<(5YuBgV zRq|=|nN_}3ep*`Ep2bjX?s)}T2e{qlDs1^Y=K3A7$_Ph5bEnolymb}UiQab5KO?Y= zPHfw@Te$Eg>7%h^FX{i9XcYhH3uMjvurE(#Y#zIpYNb$1X9-Tlckr zTg5Fzg8}Kzz=uuaTO?dma$-=mYui~{{6#mxbkghW4(3HL5x0wW5&X z7amo4W%)mdgiP%^$)vD&5>m(KnO9q`?wa|oS&j@K|!U&O2t9b?)&A=IKRM&qs(1U9J{xy2+i_IH>T>IBn{oRbqb9vl) zecbZyKWbFxzmC$(f9p;o^XYDr|ppF`G|4m`*q~~HH9vN;SeHS#K07-jA_Y@@yj5jgEwT? zSV#`aohwmMe|uRTe>c4oo{WLKs3b44L^xu#{_aj_CaV&ed9~+gXE{S z+sC;Z!q$mVeWysc?dcT14|ZcDe7>At$W&7`XYuF1uy)tQf2(YX@)eXk_B%5K#NCmG zUA>(~&K-{sns3#_jXnT%@2K#*zX_Q8!zXTp0im~;-5;87YyaM0UXOvz`abtC{;>92 zLEms+91mmt+e2w($X{#aH(P1?{Un3@#uaYwwYPuOznx3|#UHmDcJAuF3r%PgV!{4d z!(Cs$)o%Shl{l&wR>>onYeAjTjgN0OQ<-s9rk^0J#xa85JE6?Tg*`6U2O=~@LBvi{ z_wCK1oKY!AG5(m#Til0{GBaE9;$%TD{xb02+G`vyH{8Wux857!&IBFqX#S^e(@r_n zgV?RMA5r>jShnrnRXq&o{n=a}tooi>Il6uD#?ZLS{FUkMZ^SoWm#Y(^oNoiPo5D*H zk##e7bmdfmYQFrTpk@~me{>}^H(tc=p@E%m{8CdUTB>_6Rnko*5V|}bvS~ugXImg7 z6-ys7MNk3_qmR5A9$KYCZ0Z&`adEAO(zn_6PSpF)&n7^6Uw20}ULTUs$k%|GuW zlB&j|G}DeZS(vVWUkHThT2m2H>z4B0x6_g`#D?o4$o(^V z&O;H7;*XGYVm;eZg1}PSy0lR@iin1M?cB6MeXL@>iE0?m*PmQhEH&3m!BU!aw^x$d+#$BnTL6Kbi!a z=UNZy%s{_8vcEdCd2d}T*Rj6;W3Bd(?^R-JBr+90WpOn_H;}^!Tgx}Whyy+mrnvJi zJ$<~8v`50kjv&thCzsZ@KQStp%JLMeea`+%FOq>&Pb_=XHa4e261`IX^*8u7mFYLp z39(|)sl{}Ntj!9nU=MecA2KXE%f5>~nU=iu^_XvCX;D>qbg4#z{4_lp}be-T$N-CrI1Osix*1ul`EZe;yA zou1eV-ivBCB3J^tTKyxtFMsTdZaZ?*JD<|KEi9}0dv*7s!fUjLQ6mDW<%DoZL}JWI zA~@hvAEbKXHTPpX^rgl8)w1bn${Fe7xxow@ibj)}2)L064{GtNS!E={A*vNeRoZF3 zvaz-NggT~NuKWi!Yyb%MQlrvB#pFoisoOn@Aj%?gMv=dCkPpg-t4N9y3LY!qX=Al& z8!?egHZ%_)tVrzYVGm&g-x9K_aivi;f%!xiOHCP77&_EA8-l>LabLySCxG^(#8tns zKv9-S8TlIe`Ljr~I!ekKMvAor>Cer$?ez*aA*RV+J50)RtrERyG<{zK^~TwVhOiZU zYrj9-nZTMV!Ux_1D=VU9C$kb6t6$-;s~4(ZXL6I7Zt|5TiMz&rf-MEj}SWtAEAt%a^ zX;I=M9lK5K>;^y&0-k|W0+O20qSxUm08$1t$QmXX7GhMT!DI*x?Zb(7h31N-=+WObg*}#p3t=&gJ$*m+Xf9t`5sXkJ5U;=5zVX3a?eo7{`26L?VAY?K zo2=(KUIC@Ig&Q0}M*u!&#k0p`T?gY8h2~Se)+fk_+gLP+$JJF&z9wOx=#|QAoAp_g zB5w6W+qXg9fR}}h4h8&0RkRw_DK$61%#n>vPQGFx8qPmXW5Vk&O$(F1xjjnQm+Y8i zyCX7==}FVXn1vpsaOTKO&MG9R$5{Bta_hh(zdw@T_S5qReG#CdLG8(CQrc!Muwt&JXr7D z9uIvya5XRm!Jg!cVK?1NndappF`_XoQprYKXteg{K*H?ZNdm_T$~p$PN`pyq6IN4S z|8tj4|8u5t2;o*HeZ@0dn@$j;@GT!9?lugsc`-mqHV+bxO57tx zr>nhs=+Es7y7Lh7b2z04?iP6{->LA~#0Lu~JMPB-3t*8anb z6pinQzFOlKcl_LA`|wk??eTKuEPkZ*2z8~^$P2+viNG-MU)7D2XWB!0|8q{r*Tlm(-pdqu^oZK8U#UY+ z?Z4-F5Z=Z*5_c&lFiJ;NoLxtyn+-4<;O6MN_UFQSNp=I+*5W6*uMQ=TpnJLFS(Y#dLS1eG1B z7K`mTqBRWUbQl4AsT+rHG|+v+{cPJK1AGgA3bje)9n}NlZzx%1Ro>mbFg$mAWYZcN zFRGQ3cD~FW5^0u5kz+_J;5#PdR0Di_vFAz5{GB~Bn%qKktz%J2c7gnkE^LtR6i z1LdEmHvz}+U`x{Q?PkwyO`Ld9oNAIsPa^kkrx8y5F#mdr`s)fR`a_Y_c=_1`=Y`ta z;uaw1dJ4X$P;df^`|+x%kgBk(YVZ3SUxO4m+)OWcErrjP8~TT$=w-(V>!Q&N-(Kv$ z$R|4?q|bH7Pfs&^kNd4pcY3blY6>2w1CAo+BpiX5&7!;ZIDMj{jKi-0PKuGg3uB9= z0-fcd&jgoMq1&%W;d23TzMR(bA=fcs2mrksVEYY6`pBm6*BCOlq>nxuBph(UK3Ns2 zV_3dnq6oZO(elSTVOkH>J~^TXua!s-_0qNakPgyP4O z)TH==lat!uP3x|clHQ_iyo}ssXw6Eu>B$`*ZV%G3s>p!F650IMsG_!HNEYOObYY>Z z{Oa^7FDy(tWv?e+7zg}!WAxO)3EalxsL!6M8vIb zsj@QCs_}fm598^X=~Z$gkU|->yp4CWuGHkzU8_!dAnz4Oi3!DOs`klSbAIT8viu+s zitK=7dj1tVpm%;=zPu9KZvHRFR$w9{JAIEQ2>+iizlXCCLB5Je3U&$(VR>bxfxv+3 zP=EFM)#1`}K6FIT^>z%3yZ8{*_B6`j_^sXOMYiYam`C!Qb=!FCb&B=TPEYr}B|WB?WwnO_C6Oe+-u< zMGmhZ8GSSkcLW8%CPi?m`#SY#?TS?04eT$CS@z-|yOhhap#QAszfB88P@^2SewO*I z7J*AmYvg3|)8It^Ek_0z=R-oJ(xx~|F``d~yMcSZJCvr3Jpw2*A5+|O`i}~%Y5bj> zl$#_sK0dTgX@^&`+YM@=3DRm1SH{nL&~ey(dm5KyGmt#N))X94pIrdNH08=V|E1k3)9GcSLVdb+tJ(5J8roMp$JH^Wv4J zxhuYtVk8bJA!VTI`xqLvxykP^*+KM^`tNakM3gA|K1-FlSw<4*FmB0a9 zV%fz};xgRmHWhk6Dr^;OYW;{Jr>`IaS+*;J!@Zhc!>FS>;}^)VVSP(nFYfY^-_XeS zNW%pb{6Bg{-)!jY?rURGt^aB^SBxkzDEkS}+@I7kl?cy1s^SE=-r95;f~|cxnwjjpQTvlr@;mft^nQ>P%)Skn z(L?#VQ4N0Cghi6*v3gPAn53^3ti?is%oE)Ce4;Y6uybt_CGo_~3-DA4j(5y`SiaS0 z*M3F8|J4F`_+JMa*y$%dk;m`u!E15JAI6!h_;~Kyzcwto-mOj0;~cmq{8xd0e6#WV zE1Caz(bi{)+2`i386U#Q!}(Y*(fhuVFFRtsA#;6zNj5~_^>q;3Rw9o{cD2vwLmix#)TRB-5phN}7*pv7kxb>!Myev{$7giP8VIQK zOiF|jDP;})RnQFz7{X>SL}Aabr3$V7`ztu%%cSsVaTe2r5cVeD42BM<3}&?xl|W$n zZc;_eQy0FF+c9Kua^UGeKzmedz-={lp*R0Y0+gn`&cHTL7Bjy8Ire4aq^uU{{{Ztq z48JPWb8Tg;&66`rr2#c*jM5mWrZQxjVeJD@m=@IgfS{?81xC51M1+PHp)=EAU3DL(i06s#M+5cS*n!8*@crn4|VvHe0gub z5~jXahff_O8G~)*o0YL4Msc9^Zg1A4tuO(=31b`)y!5#6&SP^nLyQUDXH13xL-6n} zAmzD;5XnhJPhsoC`Eg#xc5{l-KngO~L%z+3al~{wRc9<=$NH|-1N#p=^Ri11?RfCS zi4Wa*>%B8{HsDc*?f^V`KmY=O)o*y!OD=r%H-G(`u6g29U$MSpx0i+@8RIxZi8{bq zLtY<1L{1}MQ>hypP^sL>Fh%fFY1vzhmMPVnX9IJYU0#?5{anc(8#`bEu3Y!SshaR6 zItsxfc!x1=Hpg7q1Ut%Bh-WDXg0&2mz68*kYv||OkRCIJYtvN_N6f}kO%og)4wGt| zSBqr9je+LH2YM-^gE~s~9983NGX-GcxT>0{>(Q_p)o?l;k`tF6%WA9~09blQDELwz zU(z~8SvS{-?f%GsbM+d*dH(4<0mW6YR2sXusU=ZAQX%722k?dW&pkSSX)^IIATm2jdLPKHICY0&lr=18h)dQ zbx09mv1}04aGLSUIhKdM7$uFIb%bzRol#5mtRajs7|P(7!=vlxoXyBfjj^lW5KwB+ z&FPSrjF}N*WloYDf2Gh-bPGT%rFPcip=P*=nhA~eU+Z{k9lNC}0CW7f${{!+!&r!1 z_5;nqvuP8Soey0HW}CQZ=?fcaEbAs3hp{j=V`MefmU1A`&6KnV5CSb$fY{3D?+h5o z>I9UvU{;ZBtoH-whCxx*!~~hTN+~B{IXHnaN6Ja74Xl%)v_3ZH$9b6!D2})<>z&n6 zAtHG4&GpdhmJ^&KjByi=fYs@`+qHY|Rfo^te^DN1@4oTITTh}p0goDV2jG#968V4g zKmCTwzwuRH^Y5>`;>pimnXIVMiz)=N&VBNGE0f6T!5FS?*=$Gm3F<( z-lm=M%0IoECDuvLDIumb5|h zK+QQ8g+5qH3x{EVCx-;-sUEz;WSC$&3`p@bVxEBjBwp-JhvrztfScj72fZ18aYiKH znzgJkmwgp#ys#Z+KJ2R28hdkXoHnz8_TzWueO^R!&cW;CJ4YU{YaxGVg+PFF9-j0) z5J!)kR0lZQ)=8?z<_E~XsZi*(5`aP4w%1|tZ%ZpxI=VU#&CMlFM9~eH5tMsI#Dfw| zJ8DzWb-m0HT4=JQ_b2q8wA4cV{9H0qq$7!;_qsU8tZ5~2!cwfxfw4`FJc3seM8%!P zIvLxAyu^&z`J$fh!tVjB1#z8#DANOdbDp*3vn%=&+19%OAYe8-1?DV6yi^}yPJsM; zK#U`#r$&IMAf=H2$OYI4XCPs1Z58|WoOS7e!+S0dpm%=sqn|vE?gTt4&>etBHV9hg z_kG{@ZP$LoH-6QxTz=UTpX{BK_N81On5Hr=p(|TClu-4FBWgLB8LtQeBlrP?37A{z zUdr5vJdhWif;tX3mgqvQyYy_&jZz%YoU}bMt$i%12x^MyWP+GwD2lauHJyN?IxL3E z$kiILBSWhVYK?woaf%3x!8?RN(w>+j=JAw_kOhQZxBB*CG+0|13&SC*_@%T4EE2a$ z0ZBj9N&s_SbXZO^7r=)0sE;G|$}Q67WUHrdU`{fS#?~}Ts=}EDK#fR=j5!OvukW!6 z0(s4-bj{h*Vq=?9!w*Y|m@!M`d_fsx0!*rWynOoxR6dUhQT4lx!yB?_d%T-(}~pcnS`m9 z&r0P+;wZf{%yEWlQ|xz6e{Y-%Ucr2zyY^mi{>6u{-Fw!~_r3d_A9(=X z33$Y#I{=SdnDJlzo*($uYhQBxm%sVq3$J*BccN-9eb_6%ULGit6Es?wbym7|xXWGrGFy z#dJNhiqKaJ3L$b+>xz?(qF?^=K;ATBpuaPJ;n~D#J zVDi(Sz8mlOs}JGRpSla{J65r_Hnpn+d+>|HX8rOlciw0kI2Q&Ws>)v~8IqiHaT2_o zr}qE1w2PcuRKqC$u3h}NUJJceVF+;LJVgBFtlzOv0qQ(Cbx8FNwa6UxK9MD~6oU4> zXi^K7774*&a1LXdBe6Pl%rK?Cw=|9pY7&-!wTeTk8?rKA!s2+8(ZiW_WPt8dkF_{; zP-lfJHV80cV6T0XQIKeZY{KQHDlLB^E<{22_!uMSVro zrjeb48dDXR$!k_`Ekkd-BTR>&z5Zi~JYoB8oDr+>t_pN{uQRH(^aW^D_*8yoz5Y=m zP%2RxyBay$pc_e<069gBX|B0riL{CVClNGCx#D68pX9P-wXBCbXDc<+YlEyB0%384 zkuWw#;9S%GxS`ug83l{BIa?$zBW-WG=~mqE=kLJ>-v4pjar?d4+}y;@-D}vjd%avy z`5@B(NGilWS1y9l&Q6V475TYx&uNaG0GQZuA+pu)trvcAEK-S%ErOS|n<4RBRQaWx za#U}QOKGS%ZY5O#P05hgWAo)TD5=26phC%4M>3}fa$0tp9d@nn1UO@!=E?>*q^NcK z<>D}yk__?DlH1a!K~r)I=^f|A$TCVfX*TxASSNLC+G+)3g8(iX4Abind{O?#B+i*s z3uwwJi|A6OW%`oZpypZx7f^;lX*zK-nPAt>U1uLWxbLZJ>yvlA|GgjYOu!=;-2r&y zp&0+y{Ijon>MLLIieJCr{L3x|XEFY!C18K@cZP zL|mG8E)JNM*OlC~r4)dg(gDc3x*lqM+7yl%VyK|--g_Rv+yCNyxZy9}i@Wc-55vS` zG8ypTgAe1rdmg}iK4QC&NeXH7y)O;=D-2|oJ3PF-^`e8GQb{8!Z>A} z2FW>>*4U!A@DM6T(sAB-nLt>yJFKOet~gAYwdaC5xWllb(*ZZj^{UrR*pCz?wN?#& zl;20T)PRQx8B-eJox|Qe`wpIc=&b*by?1}MExYdeKJ&32`+3g2{ZLDmEK8Oj!q^JN zfNTqwAyzOJc44Ss3FAN<3JNgTNhk=9a)62nNhL)QsB)RgpOFG$8(EgD)?2N&WVQ7| zYN?<1aqfBSz1Es@=7%xHT>k4x5*d zqt#%l8-RSL22SS)-V>V^M^t-WsgQH6xR=oW{C7v8n3SoY%xrXn6Sq8v(`snh7q(zv zu&4YzqlP?LDqpAji+HHtpWxVqnTcuo$tskZD0yNkQ?1rzLsy48r1xD)COZjYPLmr$ z52)jU<+C0KWH^!68SlnuP@6)k%@e;6qJ6^%nm0ZslomTM@=!%ltELkx5+>~{`Ku#5rkuHH_ z8etryT6T@uBs*Mzrt>65#!);bhGXG)C=8>n%#cV~{ypb{i_#;?Ig7)eH)5#~`vOxM z7XA|p?gZ8)(0FSJcQOvc;<-j3{}2M6sP}7`@H4mI3bp+bLY&u?m$AdRLI_dzk1XfB z+nqf0%2&PoP1_sIhadaEXP)6Y3HYWvt`mT7o}*U&fAep@?MMFnTmRy(z4qI_<5kmi z5Rwik8{5^&#;j$j7wDZBAw(DBPXPY~*54s|5i-S~hKfh$N>DcUg_PZ6^{fhm5#b(p8*|fB6}#zqvu*bULs{D(&MqAtD1M8Wyt)Rz%9# zwNTjE<%Kk^EbfV|9Y+(Plwsz4)az;1%5tx!v2bx-@NL0I$Exr2XO&A)(=l7)hCq$_ zUuy5HW1Vw$TwIMzd7xlUniKbtSChjxk)W+I?;W8jgvQTo`&e+Hs3W7aoQ82)cn(;r z%qT@8EdmyDr+Y+;Z zRL*IZ^yY%6u-R^IzWkAgf9T|-{n&>;_`6SWodkSS9oGrKH^)(f|1bRaKl?*};cb8E zSHJCBzvGoTkBrlis@1MRU*T_ORj|0JrOE@~z94D=D1?Y}5k(etK#lZJC2>&pwgnw# zCic=iD65lQB~0l?IkzLI?`grzOm<)%HY6NyaXd4xdLchaPqRAZnby9#)n&ZC|8mrB z4JyS39BJ?--5+qs+QyhbD|ABu?D~0NRI;T6vs9~pgU=1G#xn}G9^bsm93APs)X2iFL^|ZAWZGyYGS%cfo~oW@fqO^f~rHS{c<=dcx2> zOODOhs`6ZNqUbsT@obo;K}~{W?U;nJSfKZ=5)EybRM9;kD{5j~q0^I_H(&mWm%TBp z(g#2O*yo;^FXHv_Qa`Q}fS3MJga6<7#lQH5xBi!Z?q9#=TVMBWDGf~1P_und?|y^9 zd44tNYv7}j`84PjL<<~S>Ly^-fHOsaJnYsR2P#Brzhls}!Td8KfS!{CTI(v$#5;Wr z3<*%5c#^W&XEI$i8q&{e-$K{FE{$6=5-TZk9i0 z{==7^dmYu z3mjkI>Y{LYkvJYbp`l)5>+{!Eln-LmqxWyMTC?A78OM7J;{{j4U8d=Zwu!V&gY%xQ z>$$N%rHP(ZFC%(qQ>q!(H|~caOra9?X8ZyqNSo7V(4bx+e?t!(cpnKqGE7%>4-m8< z)SxZ|z=o{Do@{inB$(oun5xsFJQwTD_U6l9{_r1KZ<_ah^s&$0<~j-ZrZ}z>fS2~+ zP?Mj(^LPIGAN(_a_D}tvuYJvTf4j-2C`L9@AX9_01Y=hd1GlKEiaLi`_AZrwL-0-g zos<{7WQUNO%FM){hpj9Sg{8G`CB)5WgJ+RQ$WJbeTS}EKE-QAc48?J6tW`P&c~a`8 zjRtRn@||hBEvS-li`Nwhe$pz_jCoiz+6|4+q{^UIsIM1%A*IBa6WEZYH0j3an34=> zNkwJ_q$1y=*!b6pJQ*xLw+gb$I*$NKO-SVZg{$WA3IU@PsmF13HSm$g9_Q`9@d3X0 zg(qm+zpbdUhu({j+1cZCUR+R-2BtlVLDT<5k-(`u3nC!{?s8&68h!8Xp2T z9@^1#p1xh-d}5d`6gAQW#6#1xth$yqdJ&qSJdiwU+eNRHwOA4##s2$2*MU zfpIz@!Wc1i!W1lZZG#zY)kL@=TJtlWb0Q~oO)Pm%PIaGf$n)+%3WzLEX;ld1L5^&O6hF^yWOx(W*d^`=v6G+0h(l6A zJFSpr-hfs7R{bsrTZ;z=q|_ z+HNIAxmo%s5Gi2Qq?6BL<&~Uss)&KL3sM>uK}e-%>S-@Zictbw$xPFvgunS7B;`Sv z%bi^->*t$CfCX{1?NW*b0;@XZR4pOHDV**bAxJvMQ%~LI?Z5s3-v6FYaDINydegGq zt=ONe*zH^P8vM7rp6#|{y>3{o8dj^G5HqoH)z~IP85|X(BeoIe;o{<)uYK)luFj8~ zoNU-_Wl$2_tlU{ zucrBT$kapT=frt(8te2=kIXsn9`W7B~8^(iH~H4F_W^#`9jsO8v)Rjnjkvw6{@x*VNMiKD_lwP=D7`pLU9=% zG9d(Vl6K9FlbfV;#pU5ShJ&bHy!WJ(NNK=3U7JeglgeJF{^bEm!nsVIASH(yR}ex& z6B|vyoRImvfkv5uz!2WmOv%w!$!J62>2 zZyp9V3K@zHN%AqyYgQ8#lt^pD$;?Db!t@WJRb*u#C#n2}l&Vw=@0q3}r6htTMrKeX z&xbsR-UTHWLTCcp&GwN;9)93^QyJd#nNNN3uH4k?B;ciZTqgi8y~82*W%bs#{>j(< z%-jC#zk2<5e%}vxr;wdig1)+!8LV!EJvVP8m`-^fo@3Cbb1l(_`g1^q(4ml~L@qX- z)N1>gxCS;#RtZr#fpa29vPvEc)}{lWiAMIGeYeJY$Kh~E$_0~%q=#&5m- zgIt_nu-de2w;kJk$Nr>ee`CY$q-V2lSZ`ZaYYF~M<7rw)42~wo8f3+DUJ?Kw96mUK ztD^+)5agbpot^X5C!VDgI6d9T%=%K4C|NHSnZh&{se(OqZB++B^NrAiCY7-Uz1i4Vu#AQlRKhGl7dL3I_1l2HNuS1%iIUwqH+`~Dve!RxGVryHJC{TkH0R`^A##AVek6aD7Na5fS&gg94U6(LxV>56IW zvqGRYM_nL7tDvd`&N-JP=EY`8o;%k8@tG+kt~T@jnYlqZpOB4$A$%&nN}%b=)H zUaTQO7(@ZkG%ee8%lYLkhT}w1&Ahds+St*rI+_+@8yNG1cb=|^azE8*$dDaLIKjD4 z6VX{pDhYshk(`a_J15l+M^=Q%#!06@#~=U71uVurULP-s<2nI& zX&nLRe*DLO_?3VD=YINEzW4Y4z>jxL%ajJ`@tIssA3W3V8*C>Vn09ne_W%GO07*na zRFQ@h8PFh)YKcRLb*!l!wmIAHp#y7#{0A}0W-#T6CPZ+Bsg5DFz^1_c^LwOdFjlX1 z<6g;TQ5eUGk`c*PDI%kCh1F_9DHFqZUN^aU;EcJSjq}E-(kxVEkjo-ip#JHY(TcCZ zKU)IBLMdSL)63lR6*-_(oAXpQ8(l2#dANe%$}uJDHS3jGNc^ml7yDtGz$ahkZSQ@= zhT_;}ZePPO@z@6*=bdl=Fkk);PqJDytamNDeb0X1u{-J6pZ4tb9oucsdehLYJWU&D zI_dFO9;T``%*}Awb9XK)A|ObBO(KjDnkKSdb>uYh^s~?L%u{#p-gA0miw`n&uw>8W zg~tU)Y}|sku=tEV5Zr8o>y%9A)yshTck}dDT*20~CJ};&C641=QW{yUR&3T=LM(Wn zCE3z``;;c4App*jLVHZq@>i!ldS7UpKu|@=G#7N16b` zaK&*L@Bv~#pW%7bwOJBVEa|OhQP-q*OO*%I*#%X$xI{@Tp%F-bQvZvpN-?Q$o_RDr zMDhMd?n}zj#~-Ib*RM^LoE1NUpeXvN2!Ydt**R&m$oEH@5ZP?D-@bovb9(pu?uWke z#b>U#Mgm?^$8`em(m6cPz53M;p8k!$_4EJW5C5Szy=}ePxG9g~NABDr_|I~wvdGSz zIsiInlfO{cJIVgN55(9kV?Wii!LL>{cjsP zL^0O&+@3I0K*(>}LSQ88G_@E4>uyb9V4N-&JAn_#DF(cbpRK{rYgOY6^3|a4g9Jt##X-t}0)*h{SCLiU5kf;sgD}k9f=A$I zBcfvRK9^Ock#)EWqA1X0>d7Z>@$TRLD3AWmN4dDTWV2~mZ=;a>_AT3e%XZ(e**2`! zf%T@N?L00dd{7rY8|I@`r+1#52Z7(UT~e4Tx+9WDM=nRa&v-9Z#kh%*CtwEloKwbN?c4j*CFRL6Dt+DF$-E7NnN=kPOr7bH>U)>;KcJl0+gU6 zUDx7VCI+eWr}0YHlnl{HMU)>?Dg>XY6A~3gkTpCbM#n?u@;r0A$`t1q$HZ_4fT<1-l4mWYQIj^a(blPfd7?N`vQ*?s z?@!YC38iHEzIVIL?t4yeta;zNKlQ$07$&ZhfS1g1odCQv4v%R4H~;j1`@4VZO+WO< ze__8n4P!cDLrto*Z^3T&TBU;()e6z8^)A{)ww_)Loq_n6i44w0sV+@(lPZ#Ma)jawe4gEHlHx?mBX zgf_Oc5r*+Xne9_WV5YHfyz<~Jp$l|fPZNT!SDl?;1U(1Cv2gFKkjM~(80&%uKPrcS z8kkRZI|?JybeLOE9@^N_G`+(3SwBDX+5*dJsz*X9vZiGHI&6?pSQtH3bWasJ@;UV= zP@N}1q``>Jzvy71q-_p|!v{fO>=nE!404f{f~*;}8a4wUofK$}hCVd%9Ooh}sv@X} z7!MU<2>#^s#`nGIH4mP>^S3_yab{BBbrSF*AJ+-Mi+@<~U;pEO`inpPIbvvt(SnN8%_CL#Zr+r%$M`&n-~6mf zkZ?eVfv#!AXFcV*!3a#~iBWpZIgj_L7px!YosiICh;&^~+XTk(f-xNlXqB$Aqe`Gc zXVANa2S63+mpXgh5)ALXRxk1mtNO$hPL%-~cyby@2x5}d7rvmCTej-hW*UqX9V|2R z9ww%ANy({ev~7d;P_Q}mb{}UVnsY${R9WuHi?!gL61_%2ZIH^@ zc}Lqeth*K$3Su%har^dNo_+Q%-h1{ZE7~T|G%eF4eez=l0fl+)E+{BoU@+@Q+kB;F8$1BIx zg{N6H^nJj`K$W!Gbu0EXWP+ba>3}Pe7#iv%{s*#-D#u~Ljj@(X@KHS?W?8JMD4cgp z)1c#%MGEWiIzM23_9=Qjomqa*Tnba}Si(>fy_|3^Fs6efKp_%+OYn|i&;%Sos(gsp z#L$#Sn%LqI60r>`GBR+8jkeJSauU>{@B8NT^u`}} zyts!$ga7~ZKmT`c{)wM>%fEQ!p>H`chrg0d<8M8BC9hHNPT=M$^()i|79cpZpYCX) zRAPl9fw*ejf#+3yXtUKe*SZ0_xk|01qC7E9SCoKSKCCq6WIPZ*i3Zov#WW^ zs$bJK4qPVXBg1&En;e?#OtMKCM2}OF{5-<|{gNK8wH~N0ez}ZHNvg$Uq(HB8+V%CT z(;hZ<*Gc<8k&1a1K(5J^@ef?(9_0D@*C~kte-DG4l=a@FukDq^Z9{x!7eV0$G(7jr zUEcMMkMaITKgr>EWW8-Q_$$l*bj@ZP*lZg%n@GQkbbTN;BCQPZezKwkm5TB>rxLNT z2BR8$HQ{Pv%X+nC-EG9Au{$|kOaUNd=M$&<>eJme)SfIL$t9_ z%8^k`d2${oE|I2*%gexFIC3}+6h9K0QBW&IlY*0gSEZPW8s$=G)h}Vm36W=Wl#Y-3 z^3Q8(?%jK3``@RM(S_`Nqw98VQ{|G>DKghlzYaT}pwDlapJ7d=ypM{)Y2u}5lPL^r z=0J#z%o#Ag09p6~wZNF6emh5LB^ejV=@6o(svKfySg+RWhaP(HjSoF?^6~e-=MztG zEf0LrkLv{B#XF4gzxw;X{MX*}<~RR|fBvnneC^Ap>8OrdGwDwrvY-$gIQ;XZewHA} zAfx=#yDL`5XuHqBd=?prD~q%s>yO3z-+yb7CDy%I`HCI3uWcMl z_GXeEx?ZUF!X%+J;jw3hMDTHeo-GNs(u>b|lrzl2c}aPcYMqR8f#BpE$YLs#@>q$u z_AGf9DzaECL3cqo8zn0#)f$S1QphM_Gxb7~1PU7PTc$KszmaK@365Rc?rz+?@rIi( z+kWK3@BhrxTqgl9>T#U_ym&_d`nSIIPkzTw{N$hbXW#j{*MG00Fr~2)!0fOtv;>E| zco6m9nQeB1%8V+D*QS%*mn6u>pmt3>vZ5L#oAch>8ZdZP&U38)RyWUVV|sOZ zpdlY6Ye2~rNyx?6;Ff43B&)iXS?s&?ppd)r0)Yw-_W)q(~CAJC>WC- zC7AizW-z1yXZ{Md1e~@Z0)5vqPInlmbJBF7_f@AYCb=3p!PQ0NZ~%N^wHC=>2r>ld z&Yg3fd*&W}-*e-1OYt_XQr=VK^aZDIvdn*w3e_1(ph>Ba^yaa*%X?pPX5DXuLo%IH z5H-owW#R7KBX^#=;^IsI?v?PVbrLju8 zZ8{MZG}Mh#~1k_XURx z~3IthS)w-HO z-**qK`u1CnmlyB;{O7-R?Gf-I9@h!Li*tCO1Gazfm;ctU{DC+8ksoiGRwny-Pfqhh zFrZfdGR#IdO-%1T6Ll!!xvtnAA%qH#-&X-z<>js17U#g30bLd@c+7C&eXW9`CvJ>z48Me-g3d=3}sS755F=jUv)~@D1 z#a_pgU6R*!^S_tH_oaHD$;y&Q7;>W0N;@|Vo<*y8f=aw7xDcRt(h%`cddWVR49?+w zLktZ*G{o3)xJo^}PR zP0x0{!Mj9gg8B$}&d;xS=9xSA(C~^^yaGu|yho4mNC|Tx1UC&FbJgrw_QDt3W!<~fO$yw4I} zZHTcX?#?k(pZTK6R5rP5u4G?J2E1l}S)V(w_Keee;#9REZj0k6s6f*+_1@UXVcTbf z2b5`=R*M2bYf_%@u^~9ecDsGe?&iAxjeqyPcLCSRfEVewP5{2~M`ir~i(mcaU;2?h z`eT1(y;}RMuz#&Kv@)o~Ijh306@U$@(ZF32IhX46XJccfV4We~TIK7;S^d?s!TC-$ zrb-l3w7}2)<0y-J=0wdEut9}ht$9-tnGxoUrxVY*wj~4@$EzBAt0rINM!9ZS3x$H_ zMX3z6M`;^iaaIYXnIO2(_#5fYl8HI^&;4k*WO}`Ha|{Sf@0<))aVpcRdUjMI=p8|m zDJ6Gvc_AoBY^j0ErUqKVn0Av-7A6Pj3X40vA{r@J-q7^yKA zQ9azdJ8*Rv@iDVrx1@AbgyukTM_kak2rl6x48z0|U-=pr=l9s{I((4em5NMc6s^BH z@##IPFuCzhDuiyFiP<|Lgs58oB5sL6(2c%r==%+;ekTc9P9#PMf&kpupR(KbjOj>G zK8aM-)Ms(M+Ob{j*=^GSJB24SJ1Y>I$P z<3ZT;OpE7HwhUQo($w+Za419jriz-?y&@Q|K$8RQ`7Q5-`(tA6EnyWRJ^?z94@4!FG8Li1T|3%xVE~t|T3$7(uT{)xsRqtimx}cOsDz94<$#sAsq~ zcu(K0gfTx2++Qi>DhaDrz2^E>va+v>q61c)&t3q|X?w(`9y)4(ciw4x#mIN+dgf;m zUcC)-4tY9Z+&nb;VTs>zPT(XJRlT6Beb4w(Bom8H0S5DU;JAeg)cI zh{4fD8E@=-%jxb0`^^pdeof!57>@(ToEs<{DGWH5h`}>V zqOMr=9piY0gyd4a8{~S+`jgiV6}g%bG~w%r5N$O^5lkk0%y zJ^AQ01& z;vnZijEPE?u7GO8a~39cabn)ots)_MC=REV$})P{GmRsk{=^f!^X(twi7!7*zm7uo z+qdjbS8O%#Z}%;$b);Vf+D^yzHj$uXlEt-e(VnRRKIpwzBun-C<|G*?c_c?luHJ)>j=ps&Rg=L|F$SCyRN(I2bM8EMNo>T+z$BW_ zf1e8VJ8}PWI&`KiTp6KA!s?xP4rnjCYdupEa_Kl77^e$jXjpYChUpH6<1I=#kn@4# zcq!Gt_vBpItadzj;}JI9nlWE63};N!ktq#YJ&y!01EBhTON^djyj<`CCVft3w!heE zhuNJ{lM^G?n&oa$8LH4%EO8ajeL)7KX=X{tm*O4cDlsro#`*ia{xhDP2m7h;HVjgw3~j3E-dZ`Ygk zcfaBlH$V1)_kZe1uH}K>(BnD*_{JRp=zs7BzyFcH`13#e&tLc2*Z)4}WV)X`$O`AP z*fg94U*>8d&ussoWE=^2(o^?d2sj3T+vw9WZv%@zE&DH+tj@?!vxTVbB$<>Z9dWB> zKBy+%`iEs1gyj7DuAvE@VK`PY;by%NCU!d1%Gv^y1)q|~MP-Wwca?%kb*pKKl#cp3 zxmIAg3?wz{DP>T^ASn!c6p|l;Rur92Pqu5UlL0B1l+P8@zk7WTMFYG@&5l=&i+hFR z(JQ|piFdva496@z-QX*1Jq!~cc<$y9uHjP&NE&G#>lN&2GyTE!ASZ^X- z?`b=m%qJ2&xjO%e;I8Lt3#Rtk$;%aL+5%o`opr zQW9cYMtCvX)d~B}O?ImtAvo6kip<0`U9rTzK&AnX(*-60OzD6Rg;m$mw>@pMVzXLt zb$E*NtFJK(=VCUb*3M4PQKWe0IyluN)M1Jhot@#$|591|WmE-^5m1W)Z$T6Ec^YET z=RVXmCrFO1bqTOy=WE7PNlAYmBY1{t*DKdic`g;EN0G9HcR=L=$oE7>n=7j59U_%g zgi?}+5%iM=7pe@f&Kc3f!uFQngSHGJ>-FY=&35(jPk!w2U%!3(-mxyw>*EDKt`mT7 z%;AA{v)Sx_<$wLV|Ks<4?+^S`8ykjE%r;~bHjO#dN(*yo)8Ja>AnwZCB{k_<2yylW zPzJnhSjHvDS;<3gHiH415-5jNSgEKEUlR}W^9L~E)l8By7+=p(;m9-%TwGo;r6QY; zD}-2>ri044%3Qs}Tv<3*cK|^#Z8(n*{L(Zq73p1@3{Waov78l`y?HEcCh6;Y?ZYa+ zz|H0~#$>il)b!@QWT|k;IIq{(C9#UV2bcGxB6c47O`z!-`X-Xg#N~Nm7#&Tgu5-?F zc6Q|5zx_!*_}ZI&cOvog;JuRIOpd5>MpuJ|%I7G$ zVNW%|l9bN^h=RLLHsVYs#KMjJO}x)yU#vI8X-lTQzAFqzL7RPm-~-!!OV_T1iQlZr zMGTQ_!l0N?B^f>JAVe64#NFFRhGAm2U(<9=Z9h46V64HY$orH$vRj|BU7fP-w`{r% zyX~GaiCQ7J%$Uwd>4GY4wL}uY&7*PApq)!%$_GjwXq$$^@ixcdtR}~z5=r88=K?t$ z$!TQD1LJhXFkO-JAkU&+E9Xk>(R&{R9;ej#4l+kr7dKRoh^&FRCI^-jW8_3PpL?0- z1!RTg<>lu1Db9%+z?DZK#fG#BjT<1(tYb!31j3h|zL^TK_*3Tq%n#_SP*SunXF)4{ zZ1mjBdRo30V@pmWAvkus8?XJ=*FGG7U`YIE&ouIx}nV?Sh)9HbF zYUU1?a~25JY<`W%q#Ngd6#TWnSBjap%zA05#680>aTrGO7}Q>Tbq+U1!jUnZGv$M}3smOjgCs9L z>-i%d`Dxek4$m=6q9#i@F{Z0p z-OhnjKEGJvE=`{7Gs#*iIg#>}K4;W5Kes<3GAki3uKSFZc<0q8ATd>+fJr72YHO>a z2|f^fGn4N$3vdKxI*LgqLq&27Uau!vpU)Y6%cbC>SoAvGOAOiYA z)%D~8)|!{|5SPkvyc9H0do{r~b-o2fP$A(gIK72Bme}^WQV7lyV$?)0v)OFk@Vf7Q zLwS=oQ-`6D>AUO zcSU>dr8tH`plTTht2%rKtA533dg(k+$EvEj!2?7oQ)ZhpbC*xj)J=6Q5`8qea4M|E9)tQ7N;(IGeYO6y8i;E z1~O7Cnv@GVFzfp(Du*ExWj4@KvS3j8VK9|SxxeCfP7y>Mot%<#2Gl(;O(QY37_rfk z6xpNny5~%Y9nOhrAg8R!L8Nc{*sl8Tc;JElqmO;)@vm}i67+%}*9pK2djz0=%Ugcr zRX_8yf9`+z_SbyZ>&2sdtPjcDo0}nYmawJMfC{xTe||6DHul-giwYClCS>ey``4o=zDLar=0uFf6j_n_$m{i?ycNL1_8&FYlx`jnK;IXg=ok<~6D9K2UPEY{j zICwAvCE-j2xn7zWcpu1QR$YH%v){hr+1t;)fH~qnf ze*Uk%?Vr5i_y6Iah*3y;wNLMAF0N2)o*z)m(l={mV9tBsf6*{mRkyg|73&#)BK={ELn6)x=1p zl7+%N$S1RGol5ULAaM0Gw`%O(7aKntS$8XNN3M>~*1#pWRK^7uN5|QnfqQ2Y_wFXn z?qu3crtLG+G|+WhZfqYWr88mPn-7DYYjHw?EN&um6yAl(++2{6!D)gtdG4Lx<@T++ z#71Tu6jV*oc!u#FLPiyihqa}gC5k9yt?e8Zs6g-@=k!_e9vA$KP`IG2C?RTE;Gbtr z%!z`>QxvtZNqwk#rs(sS^>aJx@fS@pytE*yM}<6%nBRoV{V1}w9helgsHGAZHnrG`9`i>;hT}sPxf6W$DYaE$xdC0woIv!yG&1bIg7k znN0L;Z2=Ur%pb|Z6)1~+txyQQQ4a!f0iBd{(l#Ak*S+S!2lw4)zxd?)&Yn9v)(z?U z__`n03BU_;Sl@sBi+|_mfA&p3_{V;6zuAXTed~>kW*+`E5ZCN{miJlhF!w8|t%3^E zs)@>6*%*>=|5QIH)w%1wc0nn);x(`?eq13~$>@t30VUlal#rKZLmq=(jb!LZ$~6kK zjpyocN2axvg^u6)^O|_fa;Qlh%q+MWoanM94+?48`FU5XH*=Az*0)F?I9?WR-xB6{ z@tJ8#42Ov!W!Zo{_%@NaBIS`W4P0GKTwVwl!ADr{8(bLcWIJoKoa`RJyNPkU#QQ+g z!qs8qLyvxrN8kA=uC5MjHi7M~VSCcC-3GQNQ4@g3Y87Z#j@UZU_feO8fH2T6tH@BfnP6n(^piK*O^*TU)h$-?(5yv9 zcDj9#o4W@|<$|l>x%oUW*jsz&E-2R{p$KxFTi`q#E5sQ1yo-rvs&^vZSO+uC)qXbow$HSY|Uwt0VYk z{u2+u?0YrASU~cw2D#Zu6Kmg5a2fUQpC@`+P?n^{?$T)>Nb92sVU`G;A?eW{lV|h(& z=PBp8GlP}3qgsi$1+x_nK51g*Q^gHkT$nSFP5AcE=*9pK2b3~y3%YXT2 zUjLIn^;7@*BM*Pe4Vz=m^CUN*P<@dNs8|KCs6xtutYq-M!Jf6!EprgHq`@lSd8%Ko zNyq%(%+6v4Wn#l_WV1>6SbP1|ci$Mpi-}>&_W)~k$iS7U45WNi26CYkW7=z#vmmPF zGD0pC=OkEYh2v|b~g&e9?;6Jkag$19xs6xjZpIQr9(*kxi@2#pcKVAXaU4)-_?_b?xY`@Zz> zKFYdA$eT_T4advEt!E44;Mkl-oKKPv9FN?3_8zPDl!qVQGNdz{i@GCN=r$x`_+BNlO|bfp!rw6QD^l>|w>Ce#hmxu*K$qph)JG9mf9 zoNw^W?BBn5rU8APS+v{iyi0vOIp0#}f8eAVC(C>bOme4Vu7i*2P^d|P_rxH{qa(}# zTvwJE2+jNj*%+MnGjfqjh4azYS@1G|$kw0jGtP(m&Pn#0R`x+Jdz&R3K7{IV5@T$- zzJ1-Q3Ge*mC%U;o1c?Hk|tpFQ;RfAwwu$LqiI``%z0dK0#ZCOFh; z*`|TzV#K-`p7-8U(yT$Yhvxpx!Th+*b6oqjmEdQ51F%VB&WJ_YX0Z9`MsO;Ns!=vn z^gT6kaSoSrg*(e40rB|i7hs%+oP?QgGYggh-%25;1}1f8z=8oTp7s*pQv*iygJYw50VTH6WqHCha*g> zu-*syolOiZi!E5r>GI-|ThC+}dF&=a%+(aBSo_6130TZ?z}gg!)wW}Ivn2*7OyGoo z*Mv1^cP_Yl_ZHh-&uZ1Ol-b#N7_{shT4hSxq&hoVm5o-?j_SH6-?nE$EPK5Z%U(%V zX5GEWKc$MECQ+#*m7&(r)kWKSd49IN^Mu%`DNd;dRd}x|AZlOU6~Ex}ltr~KdqLLz zytOH;QlDptScNWuIQW2#yH3eShpD!Zf|u4oP-vgBR3I%9C*RcbvM);(GMQ;SVgsnW z^JHC>fP1xqtcZe){wO{?@H)e}EU_xK04R zzK22oo4^0df9-Gnz#shKKi~JQAIGCkGP}PIZxi84nkR8tmu&fhXke6$Z)R?z52s_1 zG}K^kNr77ghk3kk(E%sYUsM^OIfI$2oCb}m>#h6%F&fE;G>=LUGK4_T0i0A8Mq+f{ z>6{u<7s%(7*G-^3-IPUVEimq+a=@{+FS7dGV?;oM;+>=9K@%y_8lTmCq5Lu=7ksG@Qac*SFSGW@R+E>nb z=i5KU?|%Brc%NBqVYNxDw-f8lNYlb<)w0?lGQUPN@xEFGQzy0=0x-90jL(3O(a6>R zK#~;w8BO+r4+3|atZ}hYFFqs^3^n^9Ff0edYUc=D zmLV5`TJhC&QN*9WGmdl({OpX#WT;|;__l*yW6r_ z_snCl?U~WF>KvW`Mj*9pxWe#gMJkDgA(5U&{?Pn%XK%8gu14P>t`F@&h*?+>YZQ)m&DI8$}-+VY^EpwVvs`-J1kU%ruPbrjL;Z=IRc}Z1hv8 zJ7eufO64WNd#>=?A?~5dBie&hD?g2rubNx)-JI0}K=edzPw-0pdhV5p{>GqW12c~qp-pkv!?nx4` z-_oy)sJB3osxDrUhLXVBzZH#_l88`cbNagr6aj4`SZhUci=qIGB(5@eXt*z^IwwPN z%>sZ z=v$^~l=q2^B1E1vjWkV<_odlxcdvioW$TZ8_yeDPg6kyU>v~)#0AIhu1KnHR@*}VM z=|B6Y{@H6@{T<)wFgLx~?N6NMjJZDd|0qW6(z<5B`k$dn3#yjUo5aZ~YA=-;P_nti zrTQ8Yju&Hli!sJ+gRo$3x_hq`{*p8(WF_Z{Fo$(QnLyV1bFPrG60vl+i?PBTro*3G z2UeBKYh(&yJ6m}LR(WF6)aK7r)dLjpPG_-e!s7~?ZOa2UUPj+`Wz>aZ$(FEgXs_NUx9c^Ol>%Q#BFF2!;0cHnp! zC`Cs8y5bl|$MGs~b=Gikx8eLOa&guG4cnWMll`8P%}p|AjOiZEJ7S2^v&M1f&Lwwm zU9#D3*zeYw5QTb)qml^Ds!EEP!wW_uC<(XOV65yNKvXZrFS6TzAi;!(lRjEmY zjVunKSup+WeI>{`h5vIIYdD?X!>arv1)Wck2c|qy7;B$hS}Gz1453-<3`!ohK~{Rd zWCp>^Cy{oYv`eNmN;{?20%GDbqes5X7%Sygbt4v(KEPCU)eUq$QA!1Rq)Tn|*9}`0V!iJHGtor>~`fU&kZ9*eCG+ zlfxm`a`l!!{bPUOyT9uVZ;T-_PBI%DzGld583LmvX(?rgzTfombemvW-=X zU*zY7Af!{r%A91_`xS-DmzKh%sG_;deMj@wx88E`0q=4h9^%O4r0od zlH@BLa9*nZ;TXud5L(?l$+Rm^=Q=1}D_Ehan{f`#vF=Z4V#{H;&3J@Qe&Wl#^EW@m z-Mi;9#&_r0>>76az;+*4?;QQM(Dn)62KqKKl_O&+Oj!(uX683U-^%8h4s)gDtUV-J z@JKIwhjP4sC01goC$g$2i*t(~(f{`@;(Sj^$5{dLyqEI6A^Mh-4|Q!yD9dcS8|*e) z4#N|S=~C=)edhAqb9S$=+B**Ch2a@TaGj*F?nu)?TtW1X&Hcn zD#E`=#;wVdE+MBGq$2&)4Q>LzNBI=85u#QUR}ns#0*N3Rag6|ceU1pM{@y?O>p%A9|NOuBl^drI zbklTDr!0fK=4#u>JH{HWQ@Lz|wccY%b%h(jW`+h0K@e$>!1ORz_X{HvkiDYhIrA>2 zuUD5o=Doo?SN9Fk=ufluxJ=r2ES1e{**itvr_|oG4FFM}a6Ro@hWfo(r69?}R7Pgw z5+(n+f=7DfVsta}4xBG!HybKB4^7{*>NaFIYV~4HaSDeMxIFhVgk{@Jqb+cRtJQTleVKf%Udwwe@WFj_rwKvv;gFj;@EUho%)) z{cso=hY1%GD9TdV`7TggW-3Ry)|R+AlaHwvL%q-Q`8sE90ZAAON@iR9uOviznNMi9T}}Z^^h?GT9}as+hsc`U#=o{QMrzJ$o1LJiC)tt^?XO zQuCXfhq{i87g2N#ns`qk5c#04krB8AZLe6nL{J&$#L>_xlis=6!P5`|Yq$m9kX>3- zxighdp5s_2=PmjxNK$5#|K^sPVLjqkAOuD^az)B)=Esz-ba;;%5$VGpLaa&!nH*?s zIx6#?it;PjIIG+;%bF4k;c*W3WzzjixDPROLR8F|X&QB=0i+_6085gVR!Uk7k!fNl zpCqM15C4%r@=Fgt z@bZ10M#<8R)dg5}T_5NWs{Ezs!)=KG3yF*ngH*>`vbGPDT&2W93!wHsV66j#{IqeP z&|hVVSLUz$PO4--*?hd2kC-`(25grD6d_b8P>>X9s$xQtO2Y@J{0&r5m3*Npm8!JZ zV1tp3WXYCg3E5V2b=6(zcIV#Hyv^Qw%{lU6j4{`G&y{T1{^)n9UY&E#-tXFLuV#)h zp7A`-AbCT*qZ#Uhf}HdfK`Tc5TIx{^78HAb$PWXWHcQ@2bMjzz=+}sb>RoF4-JBHi zL~Rvy#`(aXi5K%(ViO6S0a{EB+muw^W)Z4TuHAtyphO4>IkQVF&9| zy%FDrA%iCN$Nd6Hfc3cLeD@?-8duXR-Zuxywm8|nujbJpW+mJ-@$kVTKJ)3%)9S?A z-|-|V=YGDdkM7Ll! z5soz^$c5mFfVz=bniE5!fuyXLx zJQpY{8WYkcI|fOfs9YkF8Os_4rs?P^0(y%P6w9DI`x1ro>}0dfi}SLiHuPev+19yBRnz|zNhX&&+Q zipJDYizIM;4bMM!AQ#x&X$+$pFH5buN!jMfhg2+vjHjQB&$3m~vU2_?r^!7`$L{+Pw z6O)^UPk{LW7z&mm8L!uL$!u4`;8nJv1vZ~yAg93sU&tU9XU`Smw~As7|Y7qp*3W<_FNnK(KtK3^Ud%0w%0%S zz|Vf{qude#f7jb>0`R-r3b6jq{`0^3eSiFi{>0zAd*?ML)3mpRh18+Bcpw1x-=2GO ziow@mCu>!MS1)a$xtEv#ws`Q74!!rOW{APa?f`}dPXSt+T(>-X?Tf_7VF&{vP)|@C z8t#?4I-yahYWiPW^yaC0Mg%&z3@J(<=Ho#-(GAyJo5iZN1T3IWCI!@RH;X>EL7Y_= z$^lPgtj%KPC&7;IRTd4A!K${^L|)Zs!`k6FESqpt!M}f!*$X|Tfs#iqFOPiSXMTf^ z{*q7gJIS1!XU^^v&h8GJ-&wKSK^YsD50qLHt5aB?Ln*?v&%FF1q}7386$*=4E(i1g z6A52b(lZfL+;e^jGtYNL|4vezj8^CPPlSiiyqC^EU+yE+AmTM~FuNm?iU@fW@&Ki{ z_S@S&(jj)+Qfi1^a-1Ge66CbvWOJ9*ka>9d1*XYH@22qC*Q2@WY1rH*PXr9g#*?0u z;IKdP!t)PMDcpTxM=1l{>`H??+fN(d{s_2PPE(&pFsmKHUR&GIzl;B}qcheLSq_z| zjy8m0kjdkY)h6aO4Id02US(OIwH2_zNCwZ3;P+g=5Byw45>V30oMyx^l6X)`Suss}YOC({cYtP&fQU<9-Q3EKDch`!#eI_Vz~u7{I=jD&Oq0ub zeWpZC_Fau@Fi}deB1qymLmHU7PfGG}#3>a&c9qq*{-(Q6o&Ms-e(BTCacdCtyV`CO zfZzF+fZ+#!@O$6*AN=LN@ZY}ko$vVropHZlUQ1M62wH1@_?BM$VaP*B>>}8!cIQ0X z9!mg1qkF^lGk5_8<#*HoO8{<67=)e}#P9e!y*{701op67kZ%IZIrK3Q$c{rh3~LF9 z2jh?-YH$fm7af6K!9CXZ?#R~qB5ng@Oq;!Q#}mSpP#s-qi`N$l0|Cj2p(L~(nU1Xw z4njh%mdV*knSIuQFIvgai2JV``GueT6d(KO(ZxT;)z74MR@Ez5Qb5?SIk6m^)%2cS+T%iO|GIV6mq{ol(66&ER5;6VI41T8m-*(QM83@I+!nhtPj)WCM z3HnMQPG;0t#yqLQT9#_o;5ikJZWuI_5%4($zV?JwaMS7zi@rW-$bn%T)|8>#Jv%ww ze({;F{@nA=zkCfmo(11--{5x30r;J5f=~MUbAREF|MMKvM*P|MqHO@=6zxL0GzbnoAd$#CACF<#e z^-=586On-H%?YhpwT3z|4Q4YG^`PF|L9qF88Kb5B&wV5>u)Dfoa?$Y#?1f#AOJ~3K~(YTBFVnLQu2U)om#+p@FtDR z48O^HU??lj#@90DHI*Y%-E%nZfyC+VNosqD950#L9N6Y{>p-z!Z^>&RL$9o7Lnh|Wa*1BUrbW*4L7az>5=U1Wm}yV*{mqFDWO5lP&QXw* z5cezrnA*|X9yTG8RtU22)b_OFM9G`(QPKRn1_2jfnkGal!?>kQN5-<|c)Vscjy(1H z*SzmX{@nNe>?c0)+5ZhZ%e_Sce%sqE0`NQAGO+rIzw*9!|Hz;H)BoTNPrdocx)`5| zXTtO1G52OevkY`-b{YHuXWjaKumvkjLLfO|Nv)mGd-;JJ%)ak)TOfLh+Jm(55b(rc z>cQXEDbMJ&c}v3G;1-piy0e+K1GSm`Zj9hH=RThX*BR!v?^c7I?Eya6%Fa4&VZRy+ zmsk0gEQLL5pcGN1Hcz&unO~6nIGs6fR;P{QvD$i{9X3ULGTcDU_MTE!y!PyMOvlFM z<&g&uuKCahp5fpA>KBmI%-8>Hc%Xu*PT#SHOYvcaQmrPZ-d*_64^aM)8jFM9LD`fvR&SIB<(*2oB+1m)m z{+%O8TfX5zOOHf5B+f^qXU66a^ei?H=n}sE{`w+$uTi=*wsjp_?pX!U5Vh-wzd#r+5j zsYr%Cxa*-Wc6RSC&UM(0*Lw8lV3rRyCol&2*(B4oBbY-Oi=_01X}|xO&wlpV2iztA zzoYFI0r>52g3JDX_=o@K-+ap(zxiFN)vPSRjea87#-b3_Kweb)1Pnl5Y?ZlxDc=7i zb+|S-0nLd@!NRv)`C=YE-nv-CMbYZPe=+|XY#%8lRD-pELFryeS5Gc#o8d`8nd;s@ zb!q0~2|$O^_I5``cYT-DkGrEhJ{D=`Whq7Tk?no(foF4Jw^Lsw{fzR;i-}o}aDzQ5$>`n_O zrArd{ISIS?rP z+12@VaMGzPk_S&N;+;OnKpd8DPQ@40t-Gb~SJf@QMQkxwVQR-7^iA?-Ga<~%dH|Hx z;*~5Hmv(#Z84QQJAJ{hH=9* zO`Y>Jl*F+aT9kC6lr<#{Ol>k-km@{*)X-EI%i4#G2~R$G_YZvU4}QmA|EZt)$p46; z0Jq)%zs>Cy0r>521z7(VKl#_c|BwH%KlR_-IlHs2i$OO_30+jw64t-Xpu-?ob$QmJ z|7K2ebd!zF*w?!Fov=ckE4%JnuF=o)D%q2V7#l0YUI- zYoHwnHvSyQ?SY=F@EB`quN#!xtcnk{K_m~o619b*Clr!oANN^(47euZ+g}c7vUii&>^ptzu>3bD#SP|LULr2G4x%tCT@GIUU)a z!0uGpp2FrtS?`o_-56KOIAkOG={2fHM5-k%)Seh6cXP9I*y#TK7?NTAeb?qMnBdFn zoNl})JmvMq`=U3mdaz3ORqNtR0@NGx>FMVj3HJTq`wWtB!`5)G`zY&F=vfZx?xQ*bMw0iwbyFTcXWhgY1Ptr^zR ze_!2x8-E_r`92EbBq`a;Qk6&lMKV!1r ze2wioiU>41e@9{+AxOf3F4!?731k6NIQZwPx5=8Tj#QQ7bbTX{OOl*iIr#mM7T2wG z&jIPThm!JW&*I{)O3ZGeh7cNWXVQt13OS9S%(DO%_fG$Bfl@|}({(2ds&j`*S@|3U zM@XoQ!-{bj-*$33{QSp1_PJX^;O}6&O#ps-TLOkRz3EL){LR1hm;aY{eABnTTXk}0 zt{CMzSN;iO4lQkVfgZ?v)fY^EXUQWG^u4lX0nPc=d+4gnI&PW&jezo;d2c*>f-g{Y zLR76E+hV5r0#R5_1?(*ht9+_Y_v!>5Kb9oP)B(D5`kSkC(U7)<{4j`DLZ}gZd=;)1Q8hVbzT7e>So^x2b}=v&8NsvEB;fTF8S^hKwdG_%8@^@xNH0J6TcYV7=7q z=WGPO>g^0&IL%p0z#-@^@q2Y}k43$c_X4i(KXwjNezgoRWT^eK+_+|Ly4>7X80AdU zo{LwMs|&lOOR-jrwXq5@5zxN#+#U-%T{GPg8jlehb#6W6ZbR*(W&OLSWIs0Uc4VqY z?%#jJ#l^&KyJE8&KrE>+My67A-|v&^Qdm=%*n3*N_8@)eNt|5+MckAJV$OoKD{>w! zIg^l(7DD$f>ateEtMcH&L>s`)t_3)lhx@4Uhay>xiF*A3h`$Os4OCZA*zTeo3F-)p z%@%2{wyAdQ9GRKzr$RIul}L$`6K_)dbLVZJ6PawFMG?7=NZ^R1dJ+ZX~Uahp=F*Fcq57MiaR{^BdA)x zd{O;-fLENgojT}f|F6wWH>Mjw9n`D!MojgKeta;x;X)SuxDiA^03) zVka|W@kFa+>o;#!Pw>R)8`-Qjq$E81r5E`>|LL#s^rxR=wN-X!2KS$x5A051dm?Oi znbk%ZMxhJ_1(#efKzHBIjS@lCD!7tLM?zvOZm27S&}?VFPIKjcv;QAGXiospSN#~l z&PbOx4TWM0Klw5rOXnNV@4>DV_&T3ufjRX-OjE7w56b?aTwmBzQwEp3x#qk}w>{C5 zjy9y;dk@(EW<95*fUr6CeT1o9LTqkADc~L!ue^N0{<3m*zGb~0{4^v-#g24~WsPUg zD|i`9Q}1q^(VFUkOfpkFQmakVi-~&ir?KeW{{lnpYz%OAm51GXx$__fH~9%3L}FIu z=seRwEC2`pAP9=;33W+>k1}pNe)>u_C4dzs^V*Pn)Nj>8M**uIAm#32lu~9GM&d@A z*Rs}=I0-Zf2Pgblw}hO&PNS{eNf1}FR*Oa#s!Bdhj!x-u@Z=w?G09a+W67AnvcLA zW+%OGj&|7=y=qso6l&Wq0*AE-)S>$5EBD*e;U$$8=I&Wi1+TF-x*7}rn+$fDMlP6d)$1-1yL zajrYWECyNYqWab7zed&Tz=PmFqi^WzQNE~f$ul&&Y^(Pof@ zhM7>asef~lU~?&^dbsgD!~=gMfi~=CTp$d_Q<0SExKdN+3fO&=^Wf;6C-WU06LKDB z_fba&z>yPi$)2C?02?I>$7%0GUqiOc%qY2cK^zyPJTgrOPkL<2WuQ)zABPn#WmwTB zdyZSL@>7?;8r&Z|DSOUskXoUX(GxT2e2C3@JFK?b*Bve{{>9Tzf8`;M>!okEue;qQ z0N>aq!0`Ilzy9?7@Bd5h|MqYHeLq%mvB4NJkN5?=x{I-w{vh?fHI@`Cg7Z9n*A{@~ zy=$_Z*0W=S|K`4GjOne_odA7w>MZw*ihU0L5$r{ho0QCqeDy#~(uL>uJk%!$i{c9l zVi0|DPC}6XW`2Odr&fj9gutrTt`e{Xk;Q0V;~xZpu+qc_B}qc1bvWCCCE&KH$twqK z`y1^6NpPIt(Syv@WkOP8T$!sMIdwn%#x;@>pL_Zx{`vp&DZcRem)M>PyOYfBG;wyG zIXfRYIUiW>l+{KVR!YuF7Dci-`Q=jVd&?5Sj)cq3Sq}Za#`&F-05GSwk{1R(@!BFn zg+IRqIoU{Fl?J5U|2;v@aZ6-| zu~5a??Lzm8?>*-rF6v}`|L~B&aW298@8O3ZuZtTuS->(UMN0r|c%$<0!4(hg@7eA) zeUczd-NS;&F(QykHWorRs)@&LZdV}ch=%lQ7+iv!2KUjQ9SI{51hu&Xt#+^b+11kT zos>CF7YmKPy4#=W|7}90@e;DDD6*J7AFsXx(@;kUayN#0b&-)|xZxQREk#2xkNy2! z7A(SHx+G}Bf#6sW_k~XBXhRs9DcVsAJk84~F-=woq&)O{q8B9Y51{Qx^8%`r(UN3W z52ch}pI7O*kAL*zzp~%ok^#Tb?KT1U#N0fTy$G z-)~OBD_cx6ladF>7L~lS`g?yJqAH&m^~_Md52=aDCwlm^e&5>*HKaoecD;`RoqYuS z&m_zaaB~7cR19wA8a+WtQ5FR2x1z05-Owkh(OR#1@4W@_3Po~uYtAkoH;u?;We*$lI>S&us#(|&Jx?x%;|aJgdwI7=9Ic-+LRb3C5!4ik^Q|h0Wy$~92KM!t7hq4 z?(Y$a_YD0tdp$24>0FAJZvI%0+k+f_tP*y(nW|!=fvZpkCA+VGC!MAEF8*0AkB#xi zfpCD6WQ86m34}!Bd0gYvT1t;l&G!Be%dAwtMHu{y?RF8LUSJhT&(A3k;{swX>Du0czs?dgmEfKox3FF5=&XaMB9`U^fBs;|qD585MaA6viQH zJ^1QK1Kz`}J#mH}o@lY66%IO_pJt`?ppqD0hlOs7f(^)f@4>Q01@ke~*7oXm7L-AIERemNxbIr0SMMg&;qTbdUOOb@`9d5w;bET;U0sDe& z*JME?MEdZWfTShOzdP5|+Rsh=%Z+Mwd6V}RP87Kj(4~K_b}G2s_%jkU%e+$mym(j1 zgkd6tTp2g)YvSlj8l`3P@teTfhIK4-v37pp|h*Kryr{Su(CP zUU>0E>L=hk-uum*-z_Aqpysb3&HVwiIl|&?EUl=(R-McE0>BBo|BY%s9x^ zH!jPIL1pH!Y2UYx6?dh9Hgf`vV-Ubd$cc%GEXm}6HF@$mFqDls|A|sv65F{^DU7h} zoJB#DL^&QVNO^RdW?K)ZY4UXzrs@m!9Ui=kKxIB~H%=PR|C; z?yNXD8#p;%u|3JGH^~TpqnH^@29hoUZ*#<_VIz23uh?R~fkFBv%`>;eV;?vZe}`sJ zZQC=|YbQ3&`)JL4*mD|eA8p^;EJ56i>NusrNt5$u^v_cBA&^vrbk&tLg{~q?(Ml#VTd8GS%JeIVHAFDlU{<1^tf#%de2h5RF5>r8DP`bzxa^5xO4(Z| zAl~E8d2kD3Lp_U|AL~iKynGSueHO-y>O=vuY3eA+b>-pfzp2SWh7EOp75V9KX#a!CxUY6l|^<$>$V#KTtxreh(M%vYbk$1i>GGd%m1msqca%}HW= zqHNEwKX`btey@Bj_P#;x(YqIFxDfZf3EX&3H>{C4nGC5|PNjQD z%zT%}J}(V!FI_uCKf4dM9vpgN5ol3Np470=6>7Ue3D$l5m~Xv^c`Y>E+wZzltcWKP zs$4w0=9QPP*lgD9PR0(6#Qp&^*)dz&W9UCQnY0hgQaH?S%u|8h+7Zd7WQlViL578x zu~1!3XXkox{e1XMxMt3vi={c1To@V7u6LYoF*05~M7}bwL71^qo%WV+*T&W5k*jM% z#Z)J2YdTpqyaB{XemF--7suGW3dE5SZzasDpPkd@guj{iR|o~dkOvx;XtmZn$r55} zDtLl<+@m6tVT9Jq8PSmeOJEW?kEff>xc!-*{^g(MRuS-9Znp`*Z@v{^^FRN?zx(6= z&L954|K#-KbZD(IwWCAm?u-|1eyVO-g0G~pV7euy_tU{xt*zVmGFP=8AY0eP#vk$f}joy1@=Eu}p|LpiZ zBW%r8eptz>SGe;K9P`TWi!bwFp5#4g@#@Q1_Ax~bw}e%urd(YnUVg4|d39twX_V5~ zuD2ZOeWrFz$piH$+{7?I79j=mpt zEd#-atsvS?DQAPKyPrUuBR{re zEc*u!?sM_zn(c1IW|MmWG_QW+-5j0MqICj2nsv2T&*Bo@6xYo;8sT{mz7>&xn$$15 z{4e{72@+lOJM6g+u7f(lAihS}-xHDtrs;qrWq*L{EBp1FtdehaE>b#3+}QiRE!R z5ECtDZpqA@$YpRxQoA==ZO*#@B)LMuP}rPTv|1@SvEH7)>Gf|u`S?dZ^r>gyYr0_F zZob`e0KWbvKzYx5zWL63zWqIaX}3MuiYQZyQL?pXr`7+>FfTj^dmkO^u#=1&Saovv zFDiQbu;39`;Eo5W_J>#jySsl(3QAMBHAO3=7Coz**Z)G*dNaFV)~8VZM9ue8%V3e!ME)QBDPI2O7~r zP#(M_TwN;lm{@NLd7RjtPLwgBnh-fM)oUYCHsQf5iCi*eC4BBP_xYFq-=}%;h5L+a zy4-JjDr`?1yAxr(h1DAJsFdQ!gQ$`Im}QiBt)p7Wxc9(J_vqKxeD~*SUs5DqEcOMG zJgMjj-q*M>dr*z*@Bh9~h_FZ;=DjaIXVIg-`TFASM~%rYGne4zyQLpTSB7{M+P{;x zyhIv;O^*x+e6DKadm3pkXB%O=?2Fs36{Pjvd6d(_G8yp)w&hJj@gy84vwGh?4L#XcKN*cm0df&8FB&gAr;JSE$z zf=BlSP0IEJ&Yvi(S9dr+IpgB;d8@=V_4C=^}! zkJqG>DG639dE%{ad-Gp<^2sNE;l&qU^s3`F3HVyuEducMw*svH&VTjSe(Vo__xHd5 z{Or8c=}5(AggfCUq;p0Fbof2FRjv0Wqi-IJeY}@$n=XcC*aD(z#Iou=v8d?!qU;Y^ zRP~Y)wcCzr50WBcef$XgPAZg?+*UJ4d=S;XNT3GcFc(4Hf=Tlk>DC*TZt@c#i0S@Q zm*aK%mR55clj_yUfl2oc2PbN~qPA-^#-lRzfhZ*vCcOf!kd&8SNIbfL-Cbd`%WO|a zhV_KWh|O?i91^HaBzyGAhT}1D@`UiEXCCsQpL>R9zxWcXjj%ltPR|Ob=OdewiS3E9 z-nqtq1*KSEHK~=N-t&&F>0I5XG&tNp&B2Xj5|A7QkAX;0)h?^$Y!mYI(9d130I^_( zgpPf-nw7;t36?-+u|8_B>N~9OSJ2*5P&d3;z9)ie$N+o0L6__3+_p%Lek>)2vE;^n zY=Y$E0eZBGy06V@-zz?A$)AbuO|bJb^H3;DvX==>^14Pjc4UA^RFW$$(g4Z)Egn3$ z{tTxJOHE_5#g$qs+JnW%W*k8f@dmv>%Rug$>tk=Tn=?SI4 z;rPH(8%OXgF}3w9%V^Ij>IH^UYbEEA!*oRpS3qwog)3qxJwRQ*KlN+cTB8i>E(ZjY z`_*Qmt+r4 zlitq?cr11ue*GQ(?NYp0?5$$X;r6CD1S|fq%~rb>W4%wfB-aUq9=|j1onUAjy&&=V z>#g~sVpUtO;8M&TH^NfRgJt_9=Ly(HwN|Y{uM^?;7bZg`jTY?N!KxvYDF*%Egs8B! zRdoW9LAQo>R8mrE74F}I%S+|XQ&CkXQU#x4Axs=wT0D2DdQacQ&O`Ij<$v_JDh%=46k*|E6s*ttTUA>gIwKJ=nG{>ypx5qxh3{~NdP0?war>-l&PLuqb60gvxWSbW#mnSPD; z*!%SH*Ot2#`~F1=tGwm1J?bw+_1@1|l!|_`g4bew<7jnQ=tpJIM)Biw-iuAr6mY+Y zLhv6FO*2|8N%+zi?s0i7eCOuPymq^B`&*^TVLlF^_NIDpQDnaS@tli<*PuN<)z44A z@QTXp9BOt`A(-ON7K&PB2bU;3akrTg(?}PWJV6s@17q8=D4d|p_?OBam zrs>Ey44j>A&))h?Z~Te3yyeM%{lzcdq5xlSyF~!L_Ev!P-~79O`F-E_J>UPgHk(~) zt)fzm2-j_Rt+y>6w35rfVz^FJ4eI7Rw$=$Z0Kq^$zh`yNJ=w^F1Kz66qz=7*A`ydI zT4xN~`)jp+aZE3>tyyIeWIY_Jj7nbS1zSSOrpnw@*8YG)rBZ42&>8AY4?U=*9y^FQ+$zV!K*SZ|E*cXDP4!0CBrcRDa`E5k+^RtB#o5B?%h zy!tQ`9}m7_Q2hgI9p8iHob&rBRsy93h!iymE|JnQ6ndoO5su3Om zUIqHGqm9jYLdj64M|3{}JfJ2+31VKv>e2r+2%xF-|VVG|G zdwfxG#AMR>^VLnV8jU2GS6-?d^$JM`rpbIshE?NwQ4#!KsM{MSUEc*9g#7q!R1f=)jO)6>6ekh-CBH(ed=egD+)!}=yUCyk= zjh~}vgU#ql_H$-MMW_mNPivoO| z?G^!e^(H`h=R4nY_FdokU4L!8IV)y?>6P=6weN5fBHiEGD*Q!XR+0rg?14%WGq2|d zC}nT5g++CpXV!IewlF-J%8Ap2`8tpJxQ#$ zkXOnu3PW~hx$MD=L=*cvHJh~1u5?FiOr3#2_^fVJ(%}+m@VyOt2^M+3gIMtasj^fc8dVKdMm*Czx>Jf|Je6@_xJvd?e-*>oV|Z%RhjkZ z^Zf93Sj#H1sQ#ljs6It&nf*ib(`GooR~jjxz<}s|p-|K4qoEk^>ZL7YfgX^w+xChf z2ZC#ET@T;Pr`-CJ2UBwFuX&+@E*JR=#|=VTVhQBhka z5bVZSV*<1{_KA1S z9g5ejWn)$O;abo%^?d{6q)f+4>hb9NRiBXo+x3Rs_AWynxx9YB$!3eB%GLfpER+X` zp)5lhN$wGlD4uj%wHPkk(k%nV%yK0de(V zBqEM5;15ige~wRo>MN`_iS0>o$lsj)Hm73ad^fnk&%uxk@ZKkctV12%*S0Vh6QF4i zHYFz`GRCAjW@fwv46`;3j{tv5M`ut-c|`;TT|n4IaPmAOd=RA0`{{+b_-?cBys{k5 z5}Tn(K6_%>9_mN#*T5^;xUX(JEN({_!>uHadvQE|yOJp6WY0vCiKf@SSTEj3^C^0J zy2pN;B4VaqA*GGCj4Tj{pF0bXmK0_wG!7h&N}YsUASX+SEl(aGD_LQ+PDoNt4+Tw` z%Ztiazw!d8@ZR75b~ft`B73HKq%e?r($*+tV+os+En8CO!-O)(kt2mr-~{(4p7}@$ z;!nFawO^4K-q3jX>HAJyW;Zt zMMN4^4@k3OVXAvSI^coHr&aeq;9rBfb#C3G1as|5)RJ%hsubNC2KV_;BdV1wIH9q=`FAQiIWrl z#iK{uq5zL=w+O(^Ed!gs|KGp=$G+zeegA*F8pmNZ4xaHEY>r5`#_jSX?}^0(v(D%a zO{`WA`e9lTm7y(dy{bq117cO3_G&+*gE$nOX5xT*@>i?4YE+9tt=GLWkGTWM5rc4A zvz4>@0^?PsS{l>kgKGNXsoDMz<2ab-fg(B4IGSsrw;jX)M1Sa&+75nByiW|Mq>iMR zU8^~_W%sL>RM=l;hOPJZy>}VCX(UlxJKWI^|9R!!B_H_d&+zoq&oPdP&91RMoqyK5 z%6eN_Z7Sm`Q%0q64c^0#`S1391Cp$&W7MvKEGlcH3J?*2lLI#?2&! zUAK?J_BO1j5yN--+3G)W&dklv```gQIJ6v9ZS!l=6Fe)&JW-nse4^+6_!fpiHfH%~ zLBDswVxQvIAY3BtH#&i1)>G!Zugc{=K5@rCyCTW~IP9WpYlc zwI*JCe&VI)D;F1yK8Eiw7x8ZaW_%|DSdE{P<+at^CuiOPh#E#fnF$B_3i3`pgE{Q%5d>Om|8*d zp`Ro1>snUA$;pn*+K?Mb!ttQoe_6SFG_k){E-x>c>LqR3Tf*%Rj_K{E-flGC{+aP# zn@t3l$C#8WQ^7}nT`i)tE3$0O?D1| zgyAM&>YUEEYR%BQY*xnt|f63P__K8x1q~KqvPgcgdv>ol&;-HQeB+wZuy=T=3Bk zKFe?X`m>Zl*q#h*PSo7}PKEUeY<9x9hCC=`fN+QlGnsjbuq4J3Aid#Ec0;BoR{b1g(k(skqPoo0RMvN_f3Lva2F|hB1&LJLX99-YkX54G8Cj3QOX-@c zN6J^e`W&@Y-u-P)apz8UF97HNqyZAtqa`CT<+Bg7(!r8>-4j5M$%nz_54e0buRB_R zBTp@PyC{vuIq~yb_we$I@aQ4jeJvatb9=zAbCBR{Qm1k_C@(%|^A;pkT7zR1njG1! z{Svf>q>3`y*l)E2eO|`G3fv{g6{<{(NjOeNVuZ0sMzV#Kv8?S}d5hF!&5<-!AX~B} zzD_2SQfCsXHfv>?uF2yGb=p(%ij>1hEe1IWMuMIg##0W*D~4h1!1Alf8$Sl-}n8ye|x( zUOfN=guj$11%)qyeNzZ4OYzm%+Ffpp6L6x;O!;o$V-uy;<>U zJOVM$o#N(Re;0rCdnh@Q(3s}?Y5p|3ZqD>?p6uPYGm^MTle-0SwD&BE`xrrezJ3FD zwr`;6eb7r&I=BnlW;kQJx@*?BDaeL~DkRB1s@4dPk_PT>UQgp8Q+?3e26mn!_`6qt zwBG)RA61z4Fii>3g2=>DbztYt-n+j{y!=9@Y$kShl$>oWaT@&m0c9vouydz9AMB*5 zk&7d5QkafMo`3!oL`Jr|4dXbFLmn!{&X*qN@6jK0LuxER-`kV#$+!`14}Qgj?OA(4sA?%NV=T%7xAu|pX$!@bk5}2y1m6{ zXhk>*#_%!~Lkeo0=A;ipEvqA`Ltc@}Kui{lwGiJ=v`brc?OXgkxEs)PwmI-357Zm z5tW5PXU`gGPbt!9;R>ei)vW?u3Ky<{X4Dg2@EUCo8o7+LI?>woj7Zqy?}R2p0;2Ml zSYUkN*se#8d*$JA@{y(%xFlupvA4FMz~#fnhd=N|e*F_)p$y7qCu~oR>AyaK%_(fQ zu-ZTw8l{NC^WKk@xiDA;r(UAAulKsk7UNopC3+%`pY%dEBx|0G`Tb&rOu*sM@m&Oy z$4dM;_ezoGLl&3&l(_g)PZ&{z2WpSGv5Y}t*kVYAwDIenh}@jhrp(#YB74moY? z8ta}hXG%Utv4Kzh0_yzCBnFyH9FO;jvk}P;&|7F7F-iR`v)VS}X1Q02+Dz5R`U>g4q&AAa=JN4H!6-)<8C+XNW? zF-w+A?kDDTzO2YS@C%tn5bGxA z7{sXCr3OLTGBDp@(g^0wv*DyZd?Vg3CK2ioHCPph^=(CySAP}!yM=2R z-g*#iHW98>OF%H9plBHJ#53hd3YMs#&D94M^a2qGEF~r?T06LQ``Qm){$sY+w3}cC}9l_rgvfkrIX;Qmos=9fOqCN;n4F%AKCJ!L{@Ge(fg3T0f}>isPQxo}7W%FqMpdOSn*lI!C=`-<3PxU8iw^LT~Y zKUR>I9O7ahs8G;QEnbhIGp6 zOxd0ZF*SCPdlNc#ZH=n#2VkkZp>^JykMYqW6PxYG{*X8xEh)Zuc;HK4e3o&YdCS}G zLK`?9AdQ7#P*Tg5U`z3=&H^tfni?$J~j$E|(7D-e!{OC%LmJ`IEq_3!EJHUaSJ{|A2H z_rLC&-u|v1AKYcC)``_PSf5pm<-P1L5kZ%z_;c^YM@85FO)DzNr9y7(;}W~rPh`Hf z<}Io~6lu~O!f0Sl%x6;x>5x7~Yg z>cl-s;LPYC_Zhrx=PIXm^H_tF=8kGfp!$1{m+;^|Ts{(3TV?y2#AcHrAE60&S*LK07D##Hdc6ov%b&+o@kKD7AX31Rt-Z~TgI)O0>qPc%o z|ITyv0!c`Wo@WVn&f)4{m8qlcs20YOS=|voJ};oFp%MT?8fdAICG*7T+t?rO@!;|v zlfu;zauxDW$hj@fv+)H)AQjl{64%FMq(mAQ5BGfGbI+1Qc*nQA&a?Buc*}s`J4=%NCE)-2IV7yUF%% z{EE^&{F}4%QP8qs{}7~Awx@}4^mdyX$6z&X4Si^{tT__WXl(&ht(3B2iZvo05=YCz z??P3n^=K@W)==FeZK9Mdtxc3v81lvplpH}JnTz5ynIflF;|^6U5kL~dutw|rd>r?e zjKfx5`_z+v?)U%UZ~iC0@}Z|g^7DHd1-MNBY^fdp^q>8~zwp$PZ+weE=Pv8=iDF=I zlvTU2Y8jaeubM!+;ZE4`Y76$gKgTx$p@aNUIWza(Zoudc9d>xq{l^WKYkeMpjo>t* zjHJv|_XIy6s{G`c`qF)H_8-6rfwPrx5CsiN3&NTE^+%E*$rh|d(h_X`AaC_K3jQfd zBWEScz;SBae+3>rRE~QntIQK`gq#yn5@ir-E$)ium1xQ&8Bk69#wT9nmp}MLE-tUx zo(}9z5~p_(yR*dZJh45=tT%~qwK03&9FRST_|oT#ZzfzC=j&uiimTz5>Ivuzo~XO& zX{ND*^%F!O5uM)xO;9p3E&HOfwNbJnrP@2u0M;>wU@BxQO7}plCstVLXDJ=Lp z<{p@{nqpwP;%?16ER7B;l3x{Nn&9DmAq_@s>=M!n&F>X)JjsfRK&Lzj@Xu=6=0wE} zeALlOv{F`u{dMKyVq!YNxU$u4HJmXWuRUSQ-E|X`)wm;gOj@ng*z?Z5M$(6uX$^$X znEJ`JeX7Zd2}cMHZ6Y0y4CC6!rFpP*s7?Jjo$8)awpQrWBRQ`)94-wFP%|4-QM6rg zet!1uANYay{_wAS=;?ogp#V3{Eq;$}zt_@A{T^zi${<1dDbUtdCXOWDH^N zfxX(iBL;%F2~e{>wj~O)8UQzJnT>C^8gtYXhLYdZ)+EL0Bx1(gtc1t7R=l1 zHfJb9X!w^2MsnxBnf%vDdom*ebCn-vM8P$m69kQZKOoMIZ>qK$_4j)18Ue^{l#^tx z9tqbM$@JNp7}q0rUYjXHjPtcDKat2~3z8|Rbk{d+!l!=i9zXxHpXK7>iuKMa|J@l~ z^0(SlR_jC=D@~4Gcr>q;;#d+xS-aESj0zg`9wBj{q?MWc*lOF)voXnCDUif9&DxP~ z2XtcT^?(pbVBCf3E-!vdCchkn6J7)h`@1AN{?y{?L?^>jN``&xb zsoHzxVXd{RPE*Lcr*($Sd+#}Qs&-ZF+UwW%`(5jpRhytuIddmd1m;#b9ALl2N^7YZ zP9+-kXdGt|3(Bdu;L=1%nYljaFkN$+6KNELfs!{&)5P&bV}Ah#be9NF$!SEgvb(IP z%lK|wqx?U zBABE%E?CqS=e*-c6o#E5W86}6q9ThBcd?g$R_&qJAk*gP`y|N)dFako$L18JHR0~g z8f|SiiVnU$)P_m~&xxVzUAF;5GPzivh^E3&w!Xlbeo8bQt29>uZ9S7{tN`^a)M0sF z8uNT2rN*o$V?N}>ST-~@eTO8%!q0J2Ah@?Dx;*)RwBJke>2VQeV z!0S!}%)stH|1bW-U;K$L{q(;(Ytf+RGzV811uz;6nYWEA zfStgpWkjYx4E?X|KXGHw?(%$o@mFsrtm4={3m4^A>Vu+xeGz19J~auIIAL=?RaH#!6j`Q zwM#oMS^qV4b?|+x8t@RG`GpkgT@Z?bvE8~OVaU7298U>O2e`d~?LFHlImV?cC3^Ni z&W`Ci6f{asl%yQ)Cgx`JPZJ%=RGpaX%=OcTR;3K?3`^@`L9I=clGqG;#$o4Wv=hhU zi5Jf%hD~OFnMj+NyqTD5<8+)z$$M^i)+{O=ovxP_@t~AV&NefUl2PUiUB8H5m7FOh zGqos#S@Wdohdo`y{YJFk*OCWQ?<9Hlz#IsrnIKS`BWHn-Owgy+?keYD>(a}PdvI{&Fj(Lg zrO}*6#~0YSRh^AmsEt-^si&tDNb25ikDhD+GH_5f#VmI+YW1#ot5kev z5(GHVQRIOs2(clhS?$mrhZtWM2g1j=5(WZ0x7JnephJCU4@(4bFg0Y*AvJfc;FZ~nmxe*IVf zh>xCJv%ehJ?v3NTyELT#?m`*2!niS^pPa2Ei$|)!%2>p7u&DanaK~|7*-t{iNJy*g zVn^D4Tb!8X5VA_~>SFv@Rv#0JSsa~ZoXehxF`YRntIt<%z&e}p{i9tRodBuEtK`BU zqq{OT?<9UdJI8olmiHrdy&O2w%YjYsRCNgAtX|qrN*(wLFP;fcz6Zn3@gm*Fm3~co zoWwb^g0_|&_fKwNjb%SKt8EFaBmHV2_ z9c>dLqfbA-W`faw{d|Q9)N~6<+8}C;x{??ZA;5?M60CJ{wNHrhqJ*=k&Dj;gR43}O zy7*5f%V;bERgyG@vSFTQYOzwCAdEw~`oSOi%)bu&1734spw~GAkbup9`k(!KKl776 z`4|7*etUUg?6FyOeM*132>57aDc+y`^xoIX4l-%L1}9MnO;xEoCPtO&ZdS zuUpkx1h;miF)`PZNeYWOM^nA=bDF8Oaedtwc1p?F4awZCkx`f|LNI;(p+{pW4SeUD zH+=b5zsYyL{SmuMtMOmnQ}$QN#XTznYAP z`={y7+x%K~DksB940$xnjRXB!T}t$V(VLUcmx%ODpTJ8CwNlc^Fl>BX)vk*IFphgf zplZ9n-;e+BpM2$;@ADd$0bb_}KnBLo{_uN$-%b0Dyb(i}5$4tY;zuxEGm#)M)b}0@VETloGS2 z_pSbJV|2n3V(1}?Dqxs~rWNt_qN)wia7wCc24HGs-mOl%c#l%b*4hL!8I>1JZg;uldQ4>Q71pk4Fu{RY+(#~p+v&}TyQE3Zd_mgt$%Jui3r+Lv|d9Nptf7C zryFt-hQX19!Sm?t`&ZJQ1F`EG011}skdtx$ub;xRr*L}^_V?h?r#-N2 z@qHUZLa3g(=qUHNT$Tn1J8bH4+kpoU9&$KdbE=c$5Ntam==&YZMk{>&p=AOtE`^~$ zZL;_@gN^y#J=67{>XDD0J>eT)&-}UJ6I|XiN@dQOQnt+VEs}DdI~@a9&EYLAdqm$S z+;YFQh0A8ws=;P}*5Ei-)8Lq`BV(*fX4Er7-ZKtc-hA+wlp1%352*8zp^Ut_yW-{T z$nD|C>2$Qm>Oerx zqG~;W?`IOBNFjS)=`wDN+0>ToM01B?ZpI!+&DKN3O0QErfCxo0WY2(j_VhU2k~Fay z$4`Iey~lqU_zLtUL9gBGb#(v)$baYW{K6-H@Vy`Y>zi>)r{WQdi$#aET4%k*<}Zs- z{2kip=5gmpa+=qvvnyt~c7AK!*vC5WTN4tzh^O+rrWJMm)*Xxn8r<8~9}GH>Mof=e z7qJ!tzg5etQoF3?B3oOT>j7BgN}-`SIrbqE!d`N4-aaTQ6$zfdQylGqQ<9ew%qTUE z2N*9LR2G>LQ~x2_>n0JW%2|dW<-~{IJMiUS{bRoI`|q>enX$jPN?hC%wwGdc|Glu; zHjCa0t{dJ+sku@kgblOtXjhT5%mzK84#NTvRDs_0aW#o-U-2DxAY@^Agk2J+7iu8; zF{2yPDs_XM{O?z(f{PhX?o6oW7~HBPu{a;LZRy*rYXO!8@J39SSbp>aP*rj&jDzjB z;}a>}ZbyC9cI#0*329{&0j?esiHK1=2hY+?Fe%dn-}|N*;OsuU^_DVhEb4FFUoay` zNHO#bLzIbNeRHf!op5jWHv93O-EW!TFfq5K>q{m2ucndv>%!&Rp)t{P^uR ze*R~F_Q!wa*M9AHURyBW>*@d`VEEB5eD=p4zxB?)Xn~7G5v3GzF%9r_kutIXJsbg_ z?Bc0b=f>g+RT>jqy*9a~m&uYY4Wk;7{fgUtPDgWNE@n7Yy>+TO-Z}t*-GIA77|{*R zDv^^Ld05c{)8HuH*iRVohBQOr0yf^2aksQ#G$vZ2=#bSFTo9?+B7buOw=b2e$BK}9 zWK06Y>zs~Gj-QC|;-iV*{_=PEgRg(cW@C}r-c|ngSBcF9Y+UFk7t=jAJK9zp>$sB( z7|T{3L6WP}MGD!kdZgt|=il0mS~R@0&IxpN80?a_Ky+(dwlScaZzKD@NG^tLaRNZd zvRh`Wq%h%q{vbvfJb%UhmWV&)?-v1D|7}i+0nhpo6gK68O&OW>xzERe#IOuuy+8M; zM2iWytY51oRVC2ri^jc(MZ(|xjv@m*{$!?%Q0v~=8q1-A3ZC2%$!B;8&uSQb0>7XP zY2;$FXKv4!rk98ar`t^4y8eS;sE%;#{E^#U*w0oIrxV=WnK2wUxE6t5YpHB?;+`t# zhNn-T@&{iZ_@N(pi}9YR+vQYfIa{RK)aHSB$f;O%pe9ZS<#21+t8r|e?P;KiV!^E&jJiPyy;r?T4J5X!0z8Ex)(+!o6I2>;|9bfo`w&zK*&G4z2eE0o(mu$*? zZtrfnxw`>L)N1^CbC|`m6N!{}Y{w1rbcd?rp?qyDuA!pMwG8mgjQBIq8dWUs*qt_? zKTT&!-ZITD4kV_CnuK2dkojaOd@vbc$uz~=OSg`%5MXYzXV+{kl%~kIrA-rgEKnO) zR~J9=xi5U;bHDa$zw;f85*WPF*XH#)IsgLXAN;|$E`IC_Kk{$vcULL8{F!kmO!Hlz zNN1_oFn;1j-%&@=2@G{qJQ3B~;k1_y!jMb%V&maiYRt>a)X7{~EP3SZEoxg}2%J!31ive$FPuGW3Z-5EI_^UQUytjE-SOdU>J){em&==zX>k*MzBV}ct z8XtY2Z0=zi{BC7CTiI3MQjdZyJvtp5|LLxd;~+L) zdPZsGoHWG^aj-SqSy7=9#?Wf%ken;O&POa$HK)-sSnagDdG-k4wc?Sc6YDm~OM#7tdi*c=HqHWZ9!s`y7fAiP^2R zBmz=d$}qY-t%0()?__^wCexosXp=JR?K>hPLkXawxDy^X)O0AyFj8B?d}$>YH7B4t z4YW4O=EUW_#5^}Xc>f8*nEBj~J!YB!H4KSjPOUld!3GlV=x8{F!vs1B^OHmwm5aTY z76t}9y?F`O&y{&rHv5@Uo-%G{>U8SLpH^E}a^7H^Qags7UR3EV8_?QJJ-uL_UXt_3 zqX+jHh6|Dw%M#YgR3{F{iP{>E9=yf#>u++JZ^1K1BAL`OS+X%^a(3s&uH}$7e$OpX znssJKTPkzRHqg3SZ*A2|RC07@XbQ>jRL9dTNoGnOD8+jLsCvtF%j`s?uj-BriFP_L zlnr%0pepQl+pEuf_7i{m>WY7Sea(?Sa{yk8mjLBQzwm`OKlAC&{uPnT+@@YPwT3q? zc0;5}O$s!Ol&T?kql;fS59+27^<`8Y?cCPUu{#EqPuth(0JbHXk2aWs zckXKnL`z>qv~~@CQ|R-DKG~ugwJ>#uMZE@Zc!V`Opf2rJJv#y6DCjC;s{M0yErC!t zi~9M^weryuMH6hcSa>ep%m+o%Xf;dkDwiZt^1$%`U;W)D{LXKDkJc&|7lR4>+!Lav$SfBFC)R5YFvn*BXV0JpEfK8N#{Nqwguoh0+7~ zoVPYF^w^z-9w<9nI>`=IrMh0e#FtmUCv_SeM|UJ*65ShY5OxoM zE{UILdRj7P%_z1>3Z)EoZjz|;u^%LG5b-Z3lTx1Ak=lf&hd$ogz*GuH%f)#bySEfZ zPoVG!_c2L!GgGE`SIQv|gy@Nafqd&ic?QR}xJRd$nqZc}@l19v>gsvDWH+mJwKhgdx{yS^(>Q0>SmKs1_Fz3Vwg{ z9^MT~UiBeZ(G6+cqmS;0;+{-mmG(n8+-}%hD*Fp14GEe>LZ-Vug16EQ;yM+CvvcH1e#msIuP__+C)^ELGA}uMY8;ndUJ6b!M6mmFPtPH%4 zBsC^O^fp+(td&Bf$7|#^;>%0K>5Hk`<3%R`zb-7bTxoK4oVA2&2>LAFjg4TXRp*PW zc4}RBM*R2AD(JIr`OJ6cKrNhAXrDDTy#h%})01HULTa|}X~~Y5^XIfkRdl_kpB)Vs z)LKqT1a4kH8R7DQUAtZe5u05(ZMoXN10P>nwXFr`2BzSEmBIn z_uhR|W)$P^H>s#tuZ=n>^V~QccHF*DG*$NdMixcKhFl75R_P)jKc@7eM87 zcUtC{O-ln6$|3;dU&5dV7I)*UqyXuKgiw>f=vW+4b)wEE4yP9k<+9H-V6)JF2PIS0YXhq3j$dpa{+PyOagC7m8-}2+u%>Bx@dH5#!{&5)wIQ>MVTYt2g|g|L{B9 z+}yI=H?|kBxiG-rb`Qf&7Uf6nz6;+XvgAPFw+uXhu~LUW2Q#(R`pxjR1PyWc)h zu9S<5v&%zJ($M8T7~3Gcuyi)AlvfS|a&|pK$YvCQ0eAOt9YY@M)T9pS^Z*jT3 zTA*X@EbhiM1T})^gwxH78iI~eqr_M}uA~_9I zn$V{JqBUwn0{gu`v!?loRuGVm=Au9*d5WAT1-=(tK_!5P^AyKmKQT z{NMk__qcg^V7r$N`n$Mtp8sChY@rN7F5=Pl(!V_Hl&%Zy5&U-J9yRr)oUvpGSQ%6| ze7bPgm-pRVNys*zamtXcJ=l3-wZxybL zn~{8Tpq0kOeWBdh=dHo*^)27{`ga+}M?8F^P=<(Zn;TK#>T;yY9a3i0rG{HX#3V#2 z*SCMfalWxeO5s?kmpbfJp&5QgN(htLgdfX}?$S3!Jws-5K05_d2xzjE4tySjDVBwd z*gaWyP6IQMa!^Gf8Z@bA3A%&k*DusP8%9B{tx~ejEmf@7fR&ZTVGmemKrm3{)J*J0 zQX?f{o^4jP>WZuyO@=Bd%?!hiA#a%L1PNw!n&yzXfB*6){IqKcHlnt4+DfXNHHY0oP>(=!>O378uOn8?~)==Rs9H ztsfLQ%%NzWz9&+cbusedDKzi2XTL8gdX17nPl>rF?g?K5!MK5tWSI<aASxy~yP}RD&4S7IBIUO3;&tdmQ0Ii&gB*_8` zVnMen`r-Eu{6D|>Ay3}FVY|<4FRT^p{xU>#qh7}l(6urJ=FH!*ERlg zL$C^%?WeDBvU)eJ)%yQKPhVoajJ=;Z6bm(QeUK%9_3`yNx3<-*vH)}n-SX*bS}p^i zFWd5cThdQl!|;P9VJLec%$YMGs|zZw zU7+jplf+O4sw%V-cQ-IzB}!4+xXPY2;qLC1uYXN>@4Yv8>+M1+Zn3)&OB)QR|Rt6kc5S%K{KZC}~Gk#|lX@=gPApB0|X z|B^So)Yz(aI;_chPej9^=wR9ht&8JnPKK{b-Eq_|=u>;?F*&f~u;4`%WO%H8qKY0;N%s0RgA!KuU$7Y%JRtYKSs(b?^SWpa0QM{;Pil>Gf>~cRA{J!z-$DDDo*_*U2!dkegJN??Qg>x zgaX&xzcaU6AH$+Vhhp_k=aFDt~z|2U)o03ZNK zL_t(aQfnoZj5P@Iu7+(!vz13rZ3YsX;nJ_!z~HUWQ!ag-m7LJIkx)`8%=4+w(bMU` zc5_K8rdQEgrOiiq@aX=}KKj(7|K`cJpWN{pX#%`X4nP9R-}$@0@RvXF?hkyi61&UB?gDl$@jGlAxrhM>(_%n-^snJu#9fQA`8`kwgjl3^`@*?O7Ie0TB((XW z78X8|Kb|47-$TvMarl1xPB}~_aMaXL(Pmis#9E?fFCT%?0nco=&qZ-P0c+=bo_3F^ zo}#A$)IO38azP`q#v=M`wpx_N9JI8`GjEaQ=Cul*Py9{&Y3f zJxupj9~4nQ^z^M`E6wF%?()Sicc|eBAHY zY|L9W!xhu~5vQX$8X}5h2q~lh8zu^Kop|=q3;yVj62o|(%d6ybN6CIFyS;FnL$s;+ z0257xMxxFYO4m^$#LE^bWR~mU*R5d&(Wwus+b@fU6_V$UbBH-n>tt=v`%`AP9SKQi z$t2gtDA+nR4m$%@wk1%A{U%={@W5smHq3SQGFb>SS=(e|PuW_UQleJN!dS+~n+?g# zOlBw})-1`Q`y`nu1*0i~6_akBwQ@M!V2#PP7)`nH<{OW`^tb-TPyYG;_P_pL{&$G3 zUmyS1>*fFqZ#;VQ$2a5Vveuap)G66>uKqyL7FSu-yWw@TeeHGY9_4!~-{xBwZ*_5) z#W<@+i}A48{yk-{%^eK!v|94XUkoMdLOn65=Xylj)Y$`e9)okby?20rW_kjSHIM}y z*f0gHz$TovDptcz=j8Ih()u@H#43FD@bvr(`jjlZxj&ZD<5)+X;PJ$);y zWRA6ub!ulD+$b%wyoP&EpdnD?iezX9Q{s`BHld^uW#~R*;?+8`vmc}^BkdW3bL4+s zKbjGmLLa03G4%bcHnC%e=nI0UFcYDf%_0P2s zkem%FAe6~Pj=9MWkTgY;FgMp_sD(&Z`vQQF`@O2Fpot+DBsWgeiObD>wB1s*a(6wLu#hh!lB}12 zoxk2*IXX=8ONHR`(;K@Ff+}gP2fW%sKjy#FN#i+8D}6osV8Flts8Jjs1DdQe5dU zqbiJ>3!^nhM^&GFmhCb|l!~YGyXJ{wIJ%N0pxR5ciqW2HtEAL8oF+;dNaLQNSZN~~ zrU@{IB(P(3=6Yfnw&avJo#sbZZ(RHZ;2*Ix2>RH+UKa;Ifc)3~#?QX>sZW3UXU1V; zo~^(`u3V)8+waS25nrIdnk)fpr*O?>rl)5hOsiMuPGltr+2Lw#j&wB*~ zTEC&RYDnMcB!)PfAV7q{`40h}7LJV4A6s4NB*mjWn-BoPW>vK zIR^-tjb)ddzV_-w2N2nKChJ59R-JEQy!s^PLO@l8+X;r`219I2;Zzb+zz(w7m+|gf zAJe*2;MZ0LghbUNslb!>g_kek(I;(_+8{B~6()&HOU--f&{=2Vyyp)U82AMrY zEB3iWWS$uE#tqEm#%}o>KTb(IVD6mq!!hyV<~fJs5$mLv8B-=R(b5THBCqc~D2ahW z)tSbrvjfhvve|=XV~H&9FHt^#xX4W~NNk&!WwDKOz~dgik^!)KyaQO*^A#AfShOpP z5s-e5kWaYs$uMvq=lv-sAcc9+PK_4q-5bZy`)uoom|@qZHdA? zj#K5uGixAv?=hrOx&&@_iZR(+VSXMy9+60T2y@p|D>tKsO%hUPJ z>QE+-Ezz69oVX}yDYG-VYBlx3Vca1qlwyIOdebFUDB0SPBO@34&F4S==Rf-+U-`;+ zp75HK0bUmeAOXX>@4oeu7rT2~pnJo{zc-X@$oO_FK#B*zk?YJ0ATZKW{b5fIa`6X3 z?9wLn1bdVLv>FwqbM-4tGpKj(^My(iJtDDmm>J$A3q`SG259au7(LIj8O;-HmP%WM ze7xb%%AlLW5wyZptOC+r^D4juMW>k$->*gydt*Z>vkA`V!2V*-%a=+^%H?J48KUWQOVycqHr7w8 zl~x&JOL+KgPN3=*H8J{S2CMT;;pv}O&iaiPJHyVu(^bBW9yDu=AD!ZwJKT* zB`L$wb=bg=X{3oUiA2SPoMM^_9f2>;MqPn3}E>{fLD^`gbFP(Ia;+0Yod-cu1oDZAjlj76mEY;UE@T z-TL;fGAIGC3HuTeq`iM}1t+!AMytmj)f%3_PI)L>?(U9!^1Z@tKXP@ySgLo9F$frapgHfE?5oKN(n-Fg?H8n{yjj5kMaT_&gNfwoBo9sT4+?h*c zGNhm|Sv1mS<#?EQ@qFUu#unm~phhLa{DDS~uv#urnq5-+VKDk1BE9O=U$3^#R^jOf!jlh_%QuD1 z1q;wFCgy6~8t1IbHi6$jq0WsuP1ITgHwhYSgKFgsCeX%^_iV;XM1*O+;W*!V>0?@k zs=!dWdJL^5<{8?YTyzRH2z6HQcGGAk$;jLW>U^SBi%93$%Xzf{hD1M}?l_$))3Gw& zB@TC$!|^54oS5s(^XDfv_n~YWbHiG6t99nHr*B5G_LknJUt#wnr$W-womf@8n_$eT zMTFCIOU|S91!(4! zq@0-RERWuP<6r*KAN|xXf9-4EzFW=8kL~MqaRAD@pMLb#J8ysL3t{-1Le2vvXXZN5 z!DJn^j~Uigy2~C4&<@%%C$UvS%`e8@>gOTKvz94ccNOeefwma<^M5N8s{{8;tGJzg z-p8d2CC(n+)YEvPLQYl-6ET2aLcL625~Vn0?-t&8ykoP;q#_KX^#RXW7|Rw(iMa)u9TWW!Ff9bA zl1($-*$zFj_iHTK3{usTeIH$AuGP=)gy|j_#VCm&n!JgO(o|gUz$QV{#?AG_M;{(J zo*Mfr7&qc@tpKP69sR3YfkfAXO71MZLVy}B}KL-bmQf^8$FPkupJ*VmMwFA!8G5v z6FO4T7DWxuvAV1&8?7%%;&iLreRLuvVHn`{C2X(g_gE!Cn?VfVni8ZE?2$xaL)FB# zLapu`)R9dV&tO>wF=eHU)vGA#;6p`q@O8x2siw*_J1|#;QueNZXC;$FWOl4fhAe_U zB8d{tKY%34aM5Qm9%sBc?`y8#DR{C-f!On1)>cJ#=Wj<5-8;1?GRcbq#V2}h8 zqLFj4?IhX<UqG7hB5~1Wk!m6pkpD_Y$fJbyh&mQMM48PNY`QHn|?Z5E7wg z^ctlV2c3BY=gyM2@uocxGZH zo2^BJft-#KLm2*e#ex}0rOtu?LJ4T8^-K6DOFAHa$G6kf_WrjS-?g)0X!kB-bQX<= zOB9A;1Gt*$hg z%Z_qVIh6M?U#e|LfoXoo|4HQ9j16*Tn%C-h1!8pD(#sUC0#xbIx5b zqc1W<k||YL0b?1<^yPoK5IL zSf}QSHTzJDu>lF}L$x+A>bo<{n%R5=BA4cVs@vI|r%a=JN#7{9^J-PwzP)?wU+O9dw6>Ue)=75l?oS-SkcIWM4V`q)p z4yc}Z_Uyp!fk(}{a=s8NAIvcBX2v~C)8cpqkT>fu^GhK34R*_MJo0j2@BHSIsuNfc3e4pF4&XQDTFZ3X7IO}vN51x9=Zx*HAJTcFCK&i^650)vKjWw zr#Zd(=KY@o{s;cd0r=~C(c<}ZQMQYw?Btj{Pd7f-x=nwF2_qkZV654EXuak(H(|XL9L0-+>Tyum_ZE_VA+Yu z0Z-K)=w2ddT~wn>)?#VCs*zz>ymO_|mE>w*5>}3kHdiuj{k@1loYBDRV3FpF@PdUf&2ZP+Z?YOcs1}+YyK`adck2sDa!z{F$+ISQaO-RbEh$M& z<*?~YmV|1iIkUh5ow$yc-B1;#NjaUAF^M6HHPhAPTn!C3dP|o!b4F6iXNc@2iZ_F$ zY827LW;Kf!4@Mt6@kmeEP%;c7 zWWS}>B@?ETrM#bfZ{+$~8TatUJ7Qg*W7nD)#}Gpjf^NGX-(o*JWNJ^D=K~UGi@NLGF2;WNUDny7sv7J58yZv zeBLk21W;O<+}SoqF)|wq@OSpLB5a90m#M(^((c^#bK&MC+`shiu0VOq6bJ(@+#XI) zF*VG*%n`#g!E}J9-vdp`#f4DD#AegT30Gn?11Qp2utx@vm zVs05|j{G-AX5vWJg3c2|9w|d1=K*bvoHNrjF;53XGN;omM#rv{P2uwL;)`#*vD-a; zdUwOeyf?td-2q6z@E`m~|JL7paR1@kk(P=myH(>qOIoL`s-^CeEa`l+Hh?WH(os%s z{F0bfHp{=ZtPnlrg_t;yIU$}B^d0~<*;*oha|M8UEL9hh#KE8925yvKO1}irR<&?{WGU*_a@~Y ztw{&w^myskR!*EF=vl||8n!ihH2OpJ?(v}p)SkKpA#qNJjJF-*~TM`>++9vPm@_U3-R4FaldDQb3NXS^1!e=-I!$hQ^rP;*V&kmjcGm!1q;*WWC(P}7 z^r%<4cmTuYD_HEeM<4n|EzOrD&{Fhso2-1m z0=7+Jcpnvz7HNJVXQMepTk;Sq!vip-_6(WlC3^6M1k=ZGSW}xwwJ_BKrEH8rG;CKb z&=aDKc|Or5_CKK++UF1dx|B}Q>E z@6@9GI!B6n_28;U!?=ERH}DHWACIKf(_v=#Z1qddzwLE(HL6_o8hmYyk~6iQd@@#| zM}Ps)7W_cR6}S{}Z~NPg`Qm&mYyw05N2;>9qafNmI!_qSUu|)c$P%<3!NxVP2hXGb zRbwLYh4RDiG_GGZuHJ-U3n3*U?r1bD0vDVry4OEVV4qIOG7tAB2)c_}R*qcDh; z`N(!ZSQs3OV4WQ>%V>XkIP&LnVV) z=>^22$@BBDHl~KnundgXd3D)GlH&8g`&782py53MChxn5?pUH|VGD?Y22=K5I;p1sitGn$mz z;#{%k(KD9eRY}75?L*;WJ8(KQnj{W4!i(oH&8DrezjEW81j&ixUBej2u4y7dPEfX) z&Hc)lM|PY0yu5vXVUS2N$@bKupbM;-6!VQJG)rh**^1Cl&2`>e-{#iu6 z)|bGtRsDU`jGCt(qu#mzhj76kkNnj@dxC*-qGO>#PbQebOYU(iXy(H|fty?9(I>6x zk3FP`q(aU+OL?b6UsgkuM+#7!w@;^o^$1>UkO?1WiUr*j6t$t8{A?@LDkNUB^axqh zmG>5gMA#A0%pg0I$@s{@CnwV+S@*D}Xf^|w+RR*qT2EGLaR)8cXCXlg9F#fl>H|Qb`St)5Kh(j2H7f)C*5I=XU`w zI&jT0ZtheEhCmEt*Axfqnq~%uowdbDy$bD@e<&MT8ypAYb^4?PSR?1b$DMe1`G9%8 z;pXLuS`&E-<35p!vO`Gay!@ENS}!X`Sg6(3ug#dK&2SwTSC<5hRy{qDB$}Z~zy83| zXsbJT@sW)$Wr<~qo@ny(unb)BwXfQ!Dw7Y?oS>AI)9H?3+*<}Oo{psC3|ChdU&M%|nUAq5;K$wp_>cdSf9I#~ z-+%B~o4<*rc}f^VSn_(Yn6gCoF~jjiRzuXr7i#aUry3o%Y@b$22)_P`&WCox8jeLE z|KoG>U_%OZ;rm-A!pAIXi*q3GyQ2_kcQcBj#Upm}lo!W=cvday1|)-N-$z=%8NZl9 zGy@VB)JXz&cZrWa*m0T~Z+=S2DZn{6&}ik3=4=j`SYITfnj(W0xNcooBsBPBVw>8?ixh;%0)rvafc>x|_y zT^k-n2t5SPw0QQwm>I_2NFLSUAh>W?V!?|sxw5d0NtSHU`BYsw0yKyMgIVU$Nm-k8iUxqoN8GN@f^vHAF8%`hCmUP}3n3~6Js!V+g;nYhz*VjL1f+1l8L z#O@+}?r;CypZUVC{PI8g^<{Q`{9Yet2Ot6E)1Ud&k8g+V!;sDujGHbbat^?WM`Nw^ zQ}dCl z2d39OwjA@{`(%fQ%bOo{sdE!MA-WWrkdBGZs%x&ta_--IP z!mxWg`+~BV0=wT3f=vX_PwYPCpjSy8>m1Bjo86f(?BSHGTOIeGtH?a=WiSNRH~{-7 zYUiFSS?^~(cEEGb{qJ=P;=Y}J|98(`x?HSR$6|l^f7)G=o^l<_CCDAe`XL}p@;;)5 zy0?4Tx)NQi_eJ)IY^m*~l^xcGqGvhQMq;^6>vGB3i3-YOZ$`!Hxe3=t&Yke3)Yt6Z zwMwmxn`>cn1t}mA;Y_goZEN8ny&r)NtAfB0ne%=ofks$w?( zMF=@^quo}50I5L9#j*mCk!2>O4Ng-)b*9zKR3~N;k`zkbASqKMxyoaMJg|tNE#t8a zQe&QvD5eyMoEV2aP)U*=zWwflF9N^$r$0O&kJrcE0l2!n_e0~jrFo4%8cU30K`^zh zR~JxQ)U5-c)vXMyr_Dmp>gju8(NT98dW0?gVGpm^B4VfibvfQdz>;iRGj>VTkLgmp zZmeTnNhDgrQ)Sy=ip4=;kGA>Hef&<~Aev0D;*5JRj z@ip7l4JoV7Uya-&n(w8G)$g{Qoc+J_iE$p`+r^OXC|EjmJti+Fu-Yb$pzCe?NFJdT z*_sNYKJ#m|!f~{~*(_p4AtGmv*pbl9`2KZuxi)sr&iXKqmDL5KUr-|Ai#Z@T5d?yT z5*e4a$YbO40C(6=CzvK>KUn6fU%tQqg_9nmh+6Y16Eo_f)~eRiLsLd z;+hC^tsD+B(?Q5D8^dr-lFIGvEw?Xc@*rHi5eC%Cj!JfY52&GVt0rVMrfh;`mH zJ?8p^>)Q`_`J(ai*_Qo7YtK8+!gd^u4^KuUyGrPQW}#;ftAZp%MhkS3cGbaXK14hN z>X#;kvf#=|j-X3|ZD$z)YltRi&rqXMqGZLwlFUh{(c?i+3}wSK9Z6}T6k~-H8EySb zj`wPnlr!@@d%JTh)nqNq^MRZPM0LEp*nb|gksn(+;K$Vg5Fq{1Fa7){AHVhPmr^cN zSNjt+Z(BqS_}7DM>je<#)%O3f_a?ozBuReX&)hxYoIAYta;nTGtE<@6Y_QoJngAOb z0EvR6jkF>lKw4|1uP1G^;)WY)(?COj1Og3#8v#OdD0Wq4zTw_;BHT?2GjsPi_f?Zi z<^@k8-#tTwhmSVf-#m2(*G2;#*T{4DCjFb~cSWZ*TmRe0-Fgt!*uD1?b@zg_^^!ohLRa^ z1E$5)s=WV8_|323?h)R7qmXs7d^nSIBG+X1IX`9*BtPh)&C?K_$u@Py>OQ$P1w}gZ zA8D7(!HWiVLhvk`$H=l60hB@1lUnpYo{~4TN5(j&co2zeP+HZ_AmV?38RrCK;<*!} z$4j-&YIUEcrIJoAMAp8AiG351V6$gKjSr%pVG|a!*sq8m%?L_OI6$3Ulr(G=w!m6P z+vQG33+xy8_{ow;YZBJS#Bz>lmELd`VfRU&$DdqqwSZUU`T5t>yz}9GA^e zUfTs^p_CJs>nB>RBw0z4E!B?Lw*oF+)7QYOZ<4$g0Ic$0f}S$DBC-YYIR->SZB9J4 z!U(7giP34#5E?pR1=KTz5+V+G)(@m*By9VIC7rm`kL0qj$ejZPC8yOkQFbPklnoc8 z)k-OuH;)hh@IU=8|MoY3`p^FS6R$KK@HGnn`S1SmAN|e8$G3lTqRgSxxW?)c>8`=n zK+PjGdV1t=yyka`l2oWJ^>;9!>7M>w+$f$GJKR~ zcz&}j4jq$}(E9r_IU|fd*&hRhn!l4H_P>lhHjg+3xz_1g*N{3fpLo-3x<8olykckJy0O-wr;)8y8IzMfOsT+9_?jGgGm zoOh{d5<;e<8^A{K2*IojmDs!Xgw~rJ=THFkz?3e~X@jJ^|BbR$g>aZPzhqV}M7m9?BaC_SA3Qe8vg>n*>Y^9o88^BW`WmsHJ zznRD|5uY=~vTbUE=gZFfPw@R;Chot4<*tERrcKU;B8cvE|OIaKo#J&*)H^;3{vXp`bTc=u^T zSQtF_+;f7B$#32Nr>!EziifBNr&UbCm276d77)Zehg}D=>-YlNqtrdx$W3cOe1>^G zVimf^EWI_Gho*f0E7Op^d<&ADNVYLkeJY&lHJRsVLO29^#slh+zII;_cKd&5?({=# ze^spD$DFkxQyVrm6YN45yJhI&K1g?PA5M4A2k#Vcx~GZ902m-k0P_UX%~D($pPAWg z7PT4*gX<0EAGy(n-M)2U=js17UboPb?Wy&;Fj)N4D!HU!Q=EG@z=S3^6L_)kh^P<=p8^Ql(>;2v#Vm zRis!@Y0!rhwNE^CJEiQ!fLf3}VHFmVBnlUM$0N;g%twi~m@#CU@wz7j}(;YuK43<&eOryb(80YY=t_#HQw&jQFWThAhm zQGfs+Qo^+r_w~bXk^?Czzxh?=dWARN#B&cu;UQ>D1RttdGYCoEzO{h8VE!|>NBqvP z1a!e_F#jksj2K}|6F^F6Y~3u0fTs{aU=C>4XhjxdHOaDlQZi7VgjK^!l1Y9|5(5xP z><9~4R+0!gB_p6BWI2&#&IrH*@wys~$a-)K;QKOin(b=?3z~oLGD&E`IMeM~>XG>k zcS3aL`0r?3fT+dZzdWcqigHSCIj5hHMY*(pL&C-}^louKNS>QH2tvVJ(A5RG=?G!h zhRl~(dtP_%r)z>>%sZ!rTncsbwM-{+@)TA)jWA`<6IQTlv6zwW_AxE-bUty`#M8EO zt#!!v0%$~&SP!0w3|CRTzGY;T23IGD+fB2vOXJ7v0yKn!b z6Bmhcn3fM(3T_&A$<}jDn;Qd0PW~W5ab_*&KZ1H10c#pL`igq}@F|5%y;>mZKs?nY z<|z0xwBnxn7aEC2*{W;l5y2e5K6Z%-Fe1&h02gpDUs>1)df_4$C_>Zj!FV#m0yjQ< z-}ue1;PLB5$}UQ1uyq~g^d2cM-Hj($p&!flH(Fv+x_vHbMLmLlPFpiVDr8wrqYfV8 zt_2ZW1ArypcZMpA6r`b58-q&%Ow8ZjM^I65CZCW9ehLQOdAAYh>KPc4ra-|Uyt1Q= zVk}|lHBw^;kgAnN#GZIxTR;?LkOe#-(|!zwAJTzfNP^mfzT&!0bVW#*W~E#@!#Rqz z78#y6p|W)?cK+RnXyGn>$0d~8ov-->%|$>})8yMk)*@!3I}ud}(z zh%7D)&-8YVYX}Weu}qFYkkrAv8QQB^29m{>Oy_`RU|@0E{dz~*b~dl7*98)w8K`ntL6`&=V|vL)cD5>pok_=eGA5Q}K~kbS8nWNtBFHphxcJjp#XHgk0H2ph z&ePaOVuDjQA~>0lV)rd6v(=AX$TZ6W5N-Nf`>h#fhMV3+#b6PF0ZSsH`g>c^Riuxx zi;o^e6Yd8~0k*7$eYb0t<=!eDstG137wdPqi$@Uqy2tUfeLP8(CSq}5Nlh3)(R!t} zM!PCC6;A8D0mVt>@!{_8{P7?Cjko{TpZ>oec!jUmC;$MYrPOzCAHVn;t&N4Y%{7RV zZQP-xfO>AL6M!JNVKq=0fooa`bh{ck!v0+ZP$cc(NZ;gA}5MEMJZ zzsOIwC&-kVW4d76?X?S-1cYdJo`-`5Vp=mOAAf*f|1$IVrEtE>G;KW?TSO>np#`&4 z3*ZaCZ~`bNazw?85NTSW1*Pof>Dd=es7JxHIt+;cDg}Mhf(S+=oET1_J;vP93FV4V z*-eTXg?XA`2_yICGu03gWiHxM;Y%K5(s#C&v4J2PbQIUKPT zheIR_59O!iRM_jk;@W=AV88*~;@28$>a`{CIp{AnlYIwuA|l?#*dsVVSx|ObM*{SJ z!o;r$B)e9BMM(xIq*vbon+XPDfH940A7fABbuBQ-nd&948=1A7DJk>m`b1S1NGMhj z6E}0~7`M5CiuFy~nCGx=^bv|PQh}tM5ziGGb6!wg$bQJWJ1oF}(t-hC4FN+#KtLVW zVz@b?!lDVV4sWeE>gd!t4Qp9L+fH{zNNDr1Pr8G|GHLo=82h~Mov2V6CX-~SsA0iK zo>|fT{2>ZRjC)ECbQguuS)o>|+_~2)r{#fdzjVY<(L^bW7br5?n^VMjK`tw8yPB1E z$F<8`vo{ZKA3=>! zS2JzplpOhw&WyWx3k#@8?i=mV{azmcnf&aXNe3G@(vuJ~QN?%N)INgmdJaG8Cbywc zqgZ;Iwk|XTacw*eF6f$bQg=JHZG;VaX9FWW;;h;n%+uK7L3% zew{eoS7-16(&5kV8n%ruQld;d70U^CcZ#~{-?a4XOyyG-Zp2NYfFbaed-nPSGC+P* zl&DXVxJQWSWn)DZdX)W$nr~Ef7mz^sP{pl0p()5@rXBqedW5sn;Lx%=tqYSs47ax4 z5Ji9ZtnGG}$E4ZHL|!_~D&xB(5lAS#zabsmW*fx2L!&p$e>5%gPyS8je)%0lu59&} zsJpS^)#uSaj|c_(ckp)UX8wo(7(w{QIk9#_?irf-c*S1Ae~USbeSaK8w+QJZY-y~o z(j)gI1dpAnA4yWUUmw_80y4tN);_RpPc+@A&Cb@qoKC0;O)tINbBx8_WGj+WuZ|yL zy=&fY(L|P$3nH7j0FXYb2J^fSG$Oj(y2fjaI8i!8@?4qH6?W5F^;IR6y_hmg>bbU9|hskXaz%V@-yyWf&dGDquw7N;%56+}58QiL64g}7BTM-hvA3*EQFz*||jFTG&PDr6KIZ%v9CL^fM(YLEx2tdT^sbe_iLN)2$-4!Z> z7zP+lt!CQ3K3BG_@aDS><;uRPX=7d{*ox+??E38H?B?CFu`Ox!_=Zb2rH24vz$qtt zs)K(F1wbbnu2CwS9+xoDn_hx>;*f!xAJ-+%5$Z@haTs z??@u6ofuYaXoEp2v1{(V=u)A zE6!B)<{}+A{l=4&V}AkNNl4Di6yV5PBgcEn0XFdqmI~}z(KHS z82h9b!s;0sX2)x-cHz5MXw*i^mI6JJvZI2a-COHUDJN>Ji0o{eStJ`*N-8Yt9ioNe z#kNwm^lXdSvhg;QB^R#OC)VY@{NfkC`;Xwy{trer=&O0XMgbr_K0Yqre)HYmOOhNQ zVlWEZyH03Q>ZbGNrFBUY1D-T$#Uo5304IFu9*ok3g7DGnfRT+T>aZR}f12a)4>~=d zip?iz=zWQXm7J~Qw4iuFp$3u2H!K#e$#`9WlrmfWWaIPxG~F$>JD;fS8FcT=y=}^G zer*-fL^k%#i)RRKHnoFBQrbRT48i zV6e#qsrWwVzO^w0MX3vV5=?!1FCJOl-4OFLCI;;furxr|GeQWMo@LB_(l}*AcZ)qH zS{%@n6^z8jZ6&u%yhT{cBWrlB|Rv z+O;)3_Obsb!$kg4L!2eBF-OOK#c$FrOkD^FtAXHE>gWRZm_HB?T+=Q{C3Eco5s)@~ z=r*6y(!qS+^h(_>Aeo%bjvksRdG+=emi)lS>wDLtg)k%cVYxsTOr!ql@pmbC z0ll*AAFWECC`~q!D3^<^@GRi;H~?>OQkn@Rz|w--a1$sFYK9|``aNA^PNclBx2u;K zf2M`&03oM4iy>+evms;4idh|0z2J~X_L~!@Q1TSCtVYuc3%kmod(Lz%h`J5oMr@vp z287b$77_ITL<|5(Qu2oUK1tM0uRwA}TJs?6O5HaTy2_a(g{8O<%b`0|@~ ze;@OUerCu1xL>bL01zOp>$=|GKmPSv-9HR&z6{CL&F{^M@`wb34yn28S8mStO%Xyw zwCbC^f2Zo`dRB}CPZtY@k~GmIn}=OYRVaBiG^~<6V8#4!2pxjAssZafCn`nuNKkpt#_&@5)|<`v-OHSzRj{Cj73w`xrZ_n$F~E z2vMO0{MJPaVy4d9`kEaz|69%aCf2DloX+HZZC)@MxqW-=oJ`Mq$v8uEIbJL}-4{(x zCeARQA8)&9J58qZuu|O!2|7ken8{OrPQR!NH*z!Y@|kz@`yzMTl`q-#S11=mmOj^G ze!6rsZl5N3PQx?p>^N7!y+)Jc-eCxG({{H6+-4?-3qwB5lYe?{cHkjQLYEFOvy{j4SF9!Rbp4kGMXQaR?$FlQ z+cP4GOrkjxM8%omOF?0dI3 z#5^y>{O=>s5zo#zVO1}6tcR}!DY1|d923DUKP9hLbSmTpjne6vfE~8K1?1|ASfaJo z_W==%I7tzTnfiD4&9qi&G;{N|%BCBwX4dt=DmqH`8XpPCJN0@&l%Mgy!pA9W>y^A- zqX3ZqhyUrn{{6RazWBO-IqZU79LA9D;-!aZV?F#efA%ev8YSGyba)Pt2QHbH2;{Ae)4urkCL!XhyP?sV0} zSo>iDYqM%tsR;F=2krYfpEich$aDw?pBI!}KuXcCN&BC*CcN}1LD)IG@BVh=kkkF* zncb2?*IGv3XT~tD>uVa!g(DvaJWI2ybN~bLcKUZ{<`ctYem@h&82MnBvs<8V-&r7t zwx{PEWS6maeV~7x00+Etvi`JS_ zN@2}s_WJDg8Ty9u=~o`_-&*i-kEIAUuhY864uvT6C1SdGi6s4~NNl1+UjA0F;055B~0dbvm8zA_`RT zoO9cu0RGt}+^K<%)$Kl|+oettxw&c@zGTO=P_#JTAXJls_98t73NErhLa)#d-xBKN7Xm;Igp-Q0Y2}dEoXTj;P_JSUD15F)j%pT$3 zKuL9g1j#VD>GZy9?cVM|&kH(oz^tFHn6!WEQ#LMPscVupfYeD5)mK&1@Lw@l+1o$mos2;$eg z?051=c>yV1Gny{;=VWK@ZpM|wDZQof-oSwZLqG(`NQ){tL(~}pn&S>=9`k?8z+Ip) zGj_QhzQ2h8IB{!QXW3m4LEVn0LU80R7<6lh4#wUeG}c0OXzW8!k-6)g)E~A~^wb%A z&LG#3<32P0kS)5r4dk3ry*N-#>en9D#{VQXF5AE4Q@v8s9dFNfyw}R}_0peZpH6v&67=R|(tE{Fz z>E^Z-A~jNzTR_EK2Cf7(Q7+df4|Z(qHB7c(001BWNkl@ta-^9>8l801}YD`N_9`2Ng-#qjSAXr-<|-J1`0OEi}^M2NImMii8(_ zn4)mp09+$)yF*wua>|A%H8b_J^z^8KUT1$>r1eGIKy!cB^nLi$53vQRp4tbf6}+)r z?#iv!FTuE*xd%qz3{zXyr+xDZX&Q`OyQbZd^PCDu2m?T%{o#jhM&OIF8bHp_xMzZ4 zA6oaR+iIF$Q92zL&*ir3lM0fS&W<7i+O&jX^eGh&a0;`p>x0P<`OHmXWk6HPWU*AM zlvXSS%*=vj)+}xoF66vWaweB#l1VZYGf9?d68mk8)q>74>m-o$o=@Wy66=&<;a5yd z-iV=L21x(y`084soM#y*ew^BY%mNg$oIMRuN$HOHE8H5lqn65uZV-G|g zz-nT_Y^6AuS_Dx`<%-1~vbzg2l1N%8DX}Cq%m`Mm?JhLUAWG5&ZD%x9l2%&s{jY|` zX&bH(b*fC5_qnr8Z)+mO+-B-sR0#Lj-F>FEGgTLA-Au!+5l=)PgQSe2Z0(7jrQ-s_ ztuUghR5fUCJ4%%#JCElRk9S{@(~34_ZyT5E6MJp!swq04u z&KHjle0VB6Jw1U~9MaqSFL=Cv$M^4l%=I_}SDrR<<7W3%y z5Q-A`8rnFm(yw@;l!EZr09{E!boZ(3=>xmE5%7Qp)C2iYx&JqYeo@QuUa=H$o$5-KVY(W@`A= z?u(1Q%5BPE>nGG)1EUYtTI(8+MjO#58RoE|+Su>guH^Ngmh_43?<5#)>Wn^^b0-Mm z*$3i+QxbaZZzs}{&Ijc$f&$GK2Zg%>&i)9rvu7I=uA%%ze*bV0*!3#wh}L&SCi_~4 zU*0rt0|7EE!}@2;1OhN9qJ*_Y`k?z$J<`kELngoxTA-_erdbsN)iIdoYyn9vJKlLk zWu%LBH%81ktMA!;TJf378(5G7<^W4>qDK}` zDCLBFrm^rQ7F!To8Wls8EoD|X%a;^8MeoFDk~ z{IA*ePb~R?ty=uT{prl(`8zJxE2@bv-+asS^_SGP@zN?W3FI-eGG}-si&2t@o${Mg ztiK1>=1`i9en>KlsrUpWM-S{m;begvD5YKtAOwfH`zoz$?MkY)mdkQSZPoU-qh;o@ zvZ#1^ZKg>@nq`0O`_&brJYr^?R_)sp=!v_#)6WQB%`1AnCILWz^wm$lI=y@Q^>;ZJ z_I*2EV1U}Tu(bloGgi8X-J@15VpK>60Fe}_F$ANFmIr!XSO$6^ibkCN$kR6sBy}d< zgYkNN!PMSN;-$as&xN^EsZN>_%tc4ce;yiFq(E6tzG+Gc#I*n75c4H1RIG?cpl5~V zA_6I&eGc4$l63gPMXi1}^g|n^ctfj)IP@m43|C`lhf`q?wJ7NzGDTL)gwTQMATrVh zB`stYYI|l>Da0}4Z89?_k`@{lgoL&XxuDGffea25q_VdwXrb1N`!;viY@GQe7d9ig zJa~gMX5|DZO}8O9h-po@wyz0baex~GJ&9|^+$2&m0ifx?Nbt=M#NhKJbo%oqVI%fhWXPDn9fVsB*GPvPt{rS^h@Zo1AX4lM>NbWo zjZf98-wA3!K&rHMv9i``OtN9;7b;bsZ7=osA3tMFA)P#Uc5_*KFuOJhNrt9byAR!D z@(@}wO`h1>`#xvq<(`N1hL6|xJYS!?U|90XDLxrDtT=svnI<{W5 z*GIvm>gxMOrUi9oo+Z6jQrnfcZ@>Ea{r&y= z>C>k}&wuQ%*Cqhu|K)%FAOFGQLOu75{fV*tMQkb%4Eev%*Vi5Eck2Qiym5;x5GsCC5yU z9n3!MA(ITve$vr>v>RZ8%`8>u^i2O|-05==T0E2H-Fq`VB&-L+{2jr5(WhgdL(W$J zbv|oMpZfE|pZ{VujGJ71h+M>%}yLRmo~nBnK0sGc0^>)mA{C*|v{ZMpL+3 zf>sD67g}@Aw_8WszN2c^x+F^%DzYe1-#~yRpNDeM;+#R2LhajSatZpgjrrSm9hLCr z6^uRvVGAR)2ZZa(| zLiI|k7O-h3gP{8S*ZOM!P}SzjSftK841v6 zx0|ayFfmOAH!FJ@409^Xf-SPGvmD$7BNu*RsxmX!V8Y|O=u4#KMO69BazrBai+)e^ z?Z|%Oc}(trV}M`~x&8_UKQXA@whWhmP7k(ti#jO61DAugU7k=nME{CsyIAm-ZJYmLM655~iTNU)b>P@mGgSXS-(J}@#*?K9WiJY=)_z_ zx58vlGK+1f6B45TUVS_wZeaq0n+}01QL;hjT1^svUPp6WP;iSHlR^^f?{O|lpHD+4 zwn~C2t&;`R6(JRt_0DOd2@{&!b(dVwNIEPo^S)NMoDCmZ7ZT%a#}{^YC=l+FoR-ft z_}$z`-6pE4}DLsDk-Isp={NKk_`*FWsn*fl$_~MJd zR`RmM7D$ftr;Z3nXt0<>T1e)P4Ci4?3so?RN(C znNi7frMQMD(TKck^9A!iGUCyi9QSuL;lG=PR!Ho_$~*NZwD!X!2lI+2%=h(fhUMaD z!HBEW@7Lar{U5^D+|T*>!%aL8_y&`n1eMP81>DsI!%`9F^2O%rYbL%Q!ap7JJdudQ z&0`%@q3Q+ddj#0)Q+H!UCa(0p$<*)ZL46%OZbd^NnAXpk=k)M?yN)*mz>UEW+t-Gb zFSNS#dzvdXSyo7}*JrbO^dLR4S{rK06e6x@+uEhHIGU;nCWdQZb6oN%dQDIC5n(C! zJs>;QtE7dhdrx)j!fCh(n~WL-zO+gM$xNG=0EN5RIB3AaJDscbLfdyz$t+1&%89L2 zO5*h0_~l z-y7?qED`J^jhuzr8XteHy#HQV?v&G;MqU<5K5-2*q`#WN`O$rA&0PkwOM7D4F9hIj zJ`du21RR;)AJ=0D0Xi{O`%aJVC&C^KCkSECyTOZ{*#vI;^!)J*x%nKwPhV&d>It_X zZ~z!YcW&~~p1y4V(7!`h20NUY-;3*RnC^JS_#9|?BPHrH3&GH=$4Q7dr`be4Ju?{c z1Og=74)7@bgzPf@dK)s0qBFs9*RkEvm(Fx0g1S5i*87x1j?lkO8Vu1gOy@(?=rWN^ zftkNWcAc*o@|aA|IrcLIACM_#<5({DIDLm64FQ$ozB~dL-K?!J@Q4|GFyXhfi++$My>6BC?X}VQR@KqK`SjUUNYF2c_8&!kd6m#VOEDo>x;6% zxcRK^%KD%t_67r%$T;xLtx8L9|0OJ|(iB?TxLnhi5!de5Q;cqW*HyX*kB08gerc@4 z`{xAEdB~BG%S0V-S8%$fU;py=^jm(PP5kp(k86g2^4qKqaex0V*%uZNYU#s$y@M3Q z)GMY*z98&!Af)kG{qxMc2kRWn@F1^*K*Ic-VNwr9@zN@A{A}HqiLnGDZG)lde2*O7 z_x56YbiOq>-zUv9g1EXs5W+z>P0MF@So9_Cj_e+}`5p1%SN>dSGWP7$-*6R7 z2EWb>W2^xp6nlCW5OkXTao_ZNXViZM?@%#!!nA+J*19=A%+L2L#KINB7e4i7xFuXz zktAF`DVl`0YwBwX{#YctRHC z`cc?6cz9gRxbHPgEO@yPnF@$_lz$=@OXbzvd<+TUWY&POmxKHb{HBO5m{`GhUQO(x{0OpBl0Zo%+V+%Mv>4o4Q= z&xV*8{d_0vB-ZtweS5YX`Z~>cq)ZE*qBr`bs1*?E){tpG==?0-H`7|iY_`}NKD6y> z!OM9OE4U@epvY6A(L7GLk+MB^+pfLEoL29LV(F*}Nru^xbU{i&G_%O!ofN~Ea0N?p zF&FV}mVxF$iMACYpj-Lst8aesCx7w>U;Nph{fiF__VJ^By%qrgApQIoKl|z3`Sg=k zHwWf{Sfi*d?E$oeNz5u>3AIL`UZ6#Z7u2!X0jtK=I%5Z1dyfMj7KM3F43)yP@!G#0 z@Wa~0c~$uMq4Dv9!3CSvZ}&btR-`C7Dc5Is|2^y#PC_qL+_Vx2(khXy;DLETQT=^Y zoHWJ=tYFW6H5`DKy4N5mVLF4M{TL0*QW(s02pTb=rueQ0_J0&E+;Sj=MB$Xa zW=Ur@{kIOdl%{KwgZ%hz2tgpm5>+WV^}Taz!Vk1Qi#8v9w;d6jBj#jb&W*oq&vvMl z>P^xRT`l!fRy+gT&w-M~su{KpgjLOI&?1dCunvMYj9~{Voz1+bO}b#Jz8vBf2CMZk z3A}~{^fGROK^0=%dfY~zP@ClFjvay7S~1dNneXfO&VrN+zg}jzDcn6|o}ZNG%axKN z$aSioDaX~bcH@Emys(sD0>^C0A!+Ytm#K6JF+H{@+7VdR)Yo9!K{c}^Xmt{3T0^pb zZZ4Fli4*(2lamQlNfx&K*@`sP#IiiF)hjs_k}T$0NQRgxNj&Bug2W-`(n~jAw@>V~ zuMdaXU3X*4Jwh00c;1ef9NMrL1pX2A}x>NSUl7CD1Nww6?Kt zmD(CPo0fZkfHj{$XVli@XPB5Oco_CIOBjB6}{UHSA$dAOy}sl>GUY%U_UYOtrVs51E4=Mc;L-&k*T7V6ruGfqkni%enu$Z(_ATvR|!? zAXjfE=!30GF!Nb*!i1MtllWDlzhW6ZO^ATV`{0!DOe z8~*ivjZ&*}y$I#hs7)6e z-RXg)6t4Sf&yfa6Sr&EJTqWf@0*2U#ml7CYSr&>cexRGlM+aYj9?V$cn2rRnnK6Y0 zV$8V__1boa4;Jte#sJMhO|)(1!*f|pT}Tsg6hg8C0nt(5nnRkVlt^+$HK9DCWD<$m z7D$cVJm>?xvizZWdsHqlx^lBK?sWGOj9V<`)zcqKy@XrPhG z!lI*CP{!g6L@S1T<%iaZv!p~4*y;xpR0OBK9@&fG4phC`xLhTR%z&I1tF4V8--%cS z0`(~ClJ98k0^&%Fq0&hsrNo-=XnLi!s|yHDE>keXds`cxsVxYF&#-`{s;wZ7_~s0< zHEToF>XaMn-MgkW=XytwrL9RDQ{WK1B7uO%*dHzkMmA^?n=!PTz-ed#-;rQP`k@xTqiM{xwl>W zg7{7RDdQd{M%mlyW3zh?a0^tOWWj82CQapiQmgGbB+`7PhOBP9OonT~3tTfGbhIVJUY* zXu>j@`p#PJ2auAxEkzQgoW1Cp$0;=Rj43rium>0$ZCO@fxxnTzIlH%`RgmnH-rWch z&tV(W()?m?jR3;hc3T4S`+t7B5F^v1{)jDIr8AF?h zNCb(YK(fLmP-!mBE6P$<_PX)u2SrlmbXRG*lXIfAj3o2bcLt+=fLo=~pzY+GX>~L0 zWGWS`(#UCHuNTk_mFj);62scq_fKr~6XFCDRklqj%@FdeVwqb=x+U~a~NwA^K0vK@WW28&AMLLzh2qZi3 z-G1E&aO6;{KqqY@EC8Vlb>@EndWj%NIrjF(^eNMib6i2!G7sbG9F4j1;ACM3lp^=s z$xlfLm-cT6Js#xHKaep7o!alFaqsVq#@|i%H=28xr!BZj#&HyJK_X2=J{>h&7c5lG z4HWCG(VuCA(#JCU%13_>W9hGSxTI^4^LK$*r~POX{`29-AG0^ej{ROW_E_|3#I=l@ z^l*RBABn;>t`3JR)6~N*B^v-&q&I6QBWfjf6)#lg?nR%|ZQD7W-k|N7ec!1DJHlQs zSRt%4+x|3|zlQi|^)pNv2v^tukrGMdWY#Ga94IVNa)u18hE>!Cx~yl4R5Y7)R-5wi zQ=_DXD?Q4AoqBeoy zsY^Oh+deb{Do}k}FQ)Zt6lkfv4|Z7EaejLL;>*eB@9M~rfqsTd|MoOH`%aax>07TFgPR{vR=p1ooP?+N zF248sIuq0oLYyFXE-2GJxLK#E?J+e|T*;&jPMw|Ri(~)dxzn)vuLo;|KXZDvCs;i0c@VGD|smVKz|D%4$s^xf`?T$nZ+p`)1eLw9aQ{ zSbuTFtL_)>&*z`>hRpl_C;ak(+^Xb-$^T?b?LbjVcSir zjiNJ>vImfR;Gm|cch*U|naWM8P9oHHH7&cEHl9>og<&IaHXw$?ZFl&ycxr z6ZF)eko4nc?Pk&>pFbBf763wrQNFcwAKs7P{om52t>_EocNSD`c*CsKzpw@z`f$T^ zo%kx+Q@d`3rx#ZH=$kV*1Am%YpYq+i0OoZ11qje&6&PHVe$(x=_vflm>A?AB*+|?=+PN*a4F1q3(jCB zIe(ssLmvYAcl^eS_qP^!f)C09J=V^ccCwi6fR~@O#HSF2RLK8rqVaZ zkSE2j5GxmQ5ZWMc2&`@EjEIXiNm$YysvFPGN?V}_tmoVDy*v+}8~GtvPY3d%x-ZF! zHem%mu#6;CC6~sX2p^vsdu^=co==~iXuG*B@9*L6;odP+B8XQ&3P_?90Zk+_>tc|@ zmhqX9a<-Drt#!-|L)KK`oll}=YR43GXww8 zy+3GF^VIBJyQpc^hhmV{vb>4;RdB0UD=)2dexY@2D`t-0yF z(!9!;Y2(=f!&(3Uxiz9|)h0o=UHR~X1^VShhaa8^WQNJ-%#neL24G7NwB~HwF#&9d zKnMjo4yp$~T2T=XG*eKqAT4p!ySa!@H`B@J$MByHDS0qge_ot_8Z!xrcAdY^mSfLn z_5pPBdOxc6eumzil^XTv;)#fg4vqVTU!7n!!KkPGaVsqNJw`X<8RGE6i|CcA&usb^s6Ju10t=zp9@gg| zUW8+TSCv&Js1jo(mmnPSTS#SC*ySAVD z_aY%wng%c8u@fpIbIIdq`u?5-Of&@d%BN4ye0rbAXQc^TcY$Xi-)lc7g$gf3Y)%B1@w+<>@M{iz!_qW;MM&CC;an zT`wdr7M9cMu?T`Rv1}oA@T+X)PEYH-TXYi(+39SWgnB9<=??6r2$C8Mx80WI8i(&&_W(Z@0SH%?F*Hdvopa`O=4T zFyjUy+)HkDh#Vf*&yNp+DBZ7bW04LoY=K!v0VCueBc#%S`nqN;AuvoM4nOc@!k>ea ztk?1R_?PLk&ezRMdm{3SJfM8w%D?eZCXj$L|NM&H2I)=W*AP5>7`HR1%o;X*19V}a zlg#7uyD-$RnK1~CbKP&(sS`e@DuHY#QzvEW9}e2{avd#eBKqR%eXv}mZVa3I-D4PL zkfs;Xip{H4vYYxZ5uajdez&iY{c&_b1YPR_#5CWc6ChCt9sO}K&U4HqLTim}tK$ne3Fh57{A*$XWH?yjg~9C3tf?izc&Qg@&UlE-rep*7*@ zV!J+Np;h6-2TzU_C7mp%!vZqR>~Gs6qxleIX1u+-Oey>kK5m8+(d za1Z5s)tMMAM`nDy zNL+I_GhOsg0Fs;i1XS}4qox0rWaLeEQ)l$e32rdNoE9?)ii3nW27t&)mhAmVBq<

d$g3_hN_*mx%fe-I`lp_)iK{O!FcjIWGHa)D-X7aGU56fA#D5Gh0+|2#fr^h>>8 z)26t27k=x&n}{_ljLZvl2AjR@N)ii_6)f!)k8)445F9a>+c-+e)4=lR#<0(Wua&3} znLu-26_6Ar=b6bLCMj0Vwc_bf!KTH8mpTR4hIG~41hc@X#q;v~77^PfJMJt$E4ZU|_z9<_Lh$RBKb#RH$r+%{mUpansoL*BAU&)q<@? zJwWXVtPzb|D`+z0KD&3)Mf#zg_m(nO1`KAd2Q^~!X}CQE!q4W@q(te|5FUi{`7PW2 zLqFJNC^ba0losr0H4lCs07*G7NK166UN<*pCqy}&%p5NRwlsBSC#19@Uch63^Jr(R zi23nk%Iy#49nh;OpZa%TmJKs6hPfF^y6*x&2nase1cF}<#6JfBN|Gl*z?h4bVor!I zh-4QgGLkYR$2?#eY*nY{FwEcc^T#s#I`)`=Fp&;o{<%Q6xm5DZ{B5TQg$GYn+Zb9u z(;hQzS@oF5J+3>piJM8s^JM($j8q*osxu(H>34tj=LHS{M63PJtoP-5QBoQ*r zgar)*#pD8f^*ECgncXlOuoT}cY7pIiR?>ko%qL%_(U$=N6jKz8M)4f|)@A12o(|zH z$%!-#{c))LobEi7WDkEOCa9A3wuu(N7sqSRClFMq?8p5L# zT|YCrALZ*c2mkUBo;dd9E{NE_G^|uTS-L-6|x!1iSL}aw<_F5;_9q3&Pz2roN)XA2 zwxu6Tdq2e+_cO)9BZ-kZ$B6xYx8sU4*@>4A2VRuC*z(br@a08FbtnO>+@LYvGi zG*8(SSy5Slou-XOqH?uVE2;-FCA67BV4xyQiyzhyp|P3S3#`t^Jth%@XKn+J$XD#aKaJ_EG?FE?>ept3#);ftNB4RS0)PPW)fex6E&_Gm`-&tCmX(bQzd!jKy@uV z=fz_I)KSi)3olBY+?Cc(mFT0jVMonUgmTW*cBR&5_V!H5%7+go1e_?e)(i;9ix-Kw zhAmL?nOZMKWbr&}l%xjmA#!GKPc-(SdHXyiN3v^rLF+ygNj1IAwEG7PRqevwwf~_Z z7DFxRC~yG)12__&X_zJeT)P0$gZ584zw)YF>>yiqPF?7RW zeKf%WL^7G|d%Aip5O2c;sg%yNb{#IvAV;ETOXPf_>eUsC5&I+l>=07bm$7$2mBdO_ ztCetCGW&BQ3ij-^Q8y(EAMm_ zmi8kVl`(T(Y+WgA^_gXr?|3Cx0Ix*=NN?Uf{_K_@&4NH}#~k<`(1LAZ_2|#x?{|V6 z<}xvJbZ+9PVvSr1sun#Q8evL>$d?Vm+f$#^Huhc>&1$KES}k7|3r1|!5cXQLs)J28 zuS!?h>xIx{v>Cx$ih*>P2Df)&C<045vA1Uvg2eou>WrY|M5`O0KK+J$-+;#Vzk=n# zkOs9?TD#g<<51{GqpWR5q`F4nhe*{UfMVS9di>Rb@_|8P1aFuVW%@InxfuzFU|Kg{ z{Cmjfvw3|e$l+rinn_c24N%62^x0Xt zf3?cjBu(u6Fpu&WD9Cu<`#-g*di;IV1sKB&i_I|_AVi7LCmmBlSDeHc(>Sv8x-!Po zP5#Gg6ss5~Q-9_w%)~sWso8U9-}rE|{JWGnIsBc)sL$T^S2Z>DPp3ZHc%vWFfH;1% zE>BX3L|Ur#$Y@tsIQ-V8Ub7;bc^vJ)hjzW;545@&?Mgd2!*&@ix$Cw;tE>(3GVWjG z!7_?8YAm=wkr!yfUaz*E-EtzNys%fZ?hH#=_s*swp|*Q*f#9`5dc(vR^Z2pr#qi8ytQwl(4Id~XG9azUDD(ycb~VhowyrZHF3 z)-h)7AUo=sb*-D>N@JR$NMdhS*9;nUcl>zW4Yt$ad26c(3pFt2b?;1G5YJVuogw$! zdw+k3RtBRKwQ);G6eUY?O{Vd~$DI$qR<6%hhv0nD1O1BFg`pwN+TpYUH&2Ow)BM}N z=aKoV__oZ~gj6*N2nRl+Gfx`~cNQ{^Ef0n#FMg+MhX*F(9~_{0C^ItyeKGFac7w^8 zUw7>Vup0Ut}R1-cMjX2jL~8mnm0&X4ai~P3^q+?&Y|{ z2r+`t_dib135|2Qd(7HAo(Niv+e5hUb8{1?Fz^4{{p6Fw%!B70^SMpl ze-WV}FWT0rr9&H2H$VGw0m;i-41uJtVVL9R-5l{5dVn*w>yuljgu8PFD$mzu)02d% zR)JK~KtSwk+91-AO@()X#NC`m!_4o3R%vHCEFaCqSFUARx%`5$1qrz z0IvR(U+hP2-=8Qy*eS}|*{r|UEs&l%4P#yfm=pMTwIFWN7kiQO$@oEcpYaGEYk z)9>^1c%|F^i<9xgeZP&Bz0~rBS(|10-2)KkmO?P;_yb45qPHl=&-4AZ z7QrAr6^q0okL>yzU?Z|ebf#4@w$L?dDUEqDJy${AT1}~LK zkQ=NwtU=6==>a&>iL*qUK^Io$y&-<{aJS4n{5T5{q5l%t=D61;iy)t4&JjpP=NDsc z$NPEA_Kaj)wOf@#P?~!)ewWYmGlZYM@4&TXqaSv5(j<6|lDtQuA$e)s#{D@P6t2>r zOA?kPQTKgP1VXf68o2a(Zs$GrWw*jQeUM1uBm^w&<7!RW)z5hB1#Q%J<X@JVJYG@QnF?DL?CiHA!KMfMpc!xlrN{n z`cc1Lg8(3aEMMFP@gAGvphlALh?)@}Jrrp7;?v zGMImF!JZY2B^b@kI5G>uhRS;qcfGB{YtAf~=YyO4{ob!&IAfK%>0CyeT?0OtZzTA& zz3-`iH)wo)`GW}`V#53Q4io3kNn#8Gi!re*S2LL4K5m_zG z-Un5hyeums-06HL@Bjor&jVd+(1SSjcD31Rbs=+=9NH5Zy)k$VG-Cj~qa(mt?fFH3 z=jrs3&ySvY-Hj(G=s*T<6zc8szCrIRLV|Dg5UHj7X=Yp(JzyE62X58U4RYOLKN_rd z0MrRXH~)zB-)md+U$xBJxKxczFc)CkwBDsu{N~%=;5Z*}xoQFPL9ndAT0=xqqeT#h z{DLACwX7fzE?3R#{pkqMRZmZ4H4L5S2h>uKvI2&bCR8CznZIch^DDpJ0ssI2dVF|% z&z!N9MWuR(9YfjdTruEKaRWZ{)Fa&zXo5RD%qKKHcPmNLxV63KtIQY;1vJL!7VZE_ z5v)Zp9dwI9n(oaRi81kJpcLwDdHcHe{9SVpn$5xx8xG?$H;>Rav#&8FX(ob z`k#Mw!>n-A>xE9&wa(E2%ZRsNbbSjKN5}dvTzjS$`^hS~JO4arXA% z4_Z(*Z|S|<2Q@Cx8Dt>lvE#Jn(wG%MnCLz9m|aV;>k7Jg-|G}Xhqtk(6_?bkB)ORu z5;CKfW1k+K7&l*g(l+`u?o-m)w3mxpP|@j_aRV-TSC^ZH9=QUW$tEJ{&P0zQtjF)FX}Sf|t*K zRB=Koa$=I zDt*O{eGZbu@XU#2jKIkWf7I$ADI;~+<=VKg-bobGc+o>{wB(nkH!e_ zh;1HgKm!fw-XaTw#N!5x?V?a`>SSnVlt*1P+FYG_JABf#070Vl^Y#+V$VtusCUXyC zsP(t(`qe)@HURJLhoNtEVn}eoa)ZroEU5h=)^}avcG^z%9NK^IzTIE0>K2d~c@m#S z!NWp&f9h&s`%9K8!@Ya_p3Z6q-ze0FJ9S*2dR(pKqalL2D6%-*oLqZ);<_QPV*dp|5J>(pq5$6)9a?E}GwT zwAzS-ygSD5drb@zHzamVOfbkE0P5aGM6lHh%K6{1TxSRY>$2Q~+1+)i5rr6Ou zV3F~PV9Jbj1F$Kxm~uvQ-3c?MpN$=uy-WX50{oVCg|foZ!q%$X%lBU1qS%Cgr+YS8e$wJ|Ldf z<7qtLO-?8HQNc}P8=g<;2#@9KZggs?tZidVYLrPmP>{BVT9BW_$9AugKlb`)yAnf%7JuzFtyhN0Lc-AGYF?PhnNoN6KkYd9a>Dov$!qM=^%lm2NP=V z#<~lTXzs=Br1B=)Q?j{8&Y|>KsGdH{<8SE!hP1t;Cjw z(B`p+(H5NpI2uFk^=_-(JUk z7U&0hena9EDyJSAQhhuUQf3QU8uAw%E9ObJ^J>q(8}lWkq{e!#0jL0~5IC8;WFpie zxGn++Av3@^gQ$cCQ&G(7*^TmhUU3!XJpQJI32P0 zsqT#kDK+&q>hx#Z1XmKA4&2UTVJ677gI)w=@FU*H^;Q4?<~&UT*fEbf86Cy7h=8U_ zt5vP@``$SKgy2CDb#7O)1JH>wXbgyY$Xd|@G?Y1s1q`aj7&ZD9OGUEin9Q@P>!g6F zKuo2cd4dq53PVGWTI4dG+ES{?;{ynQiky$SD5QePqYP>+?2IGSe_M?c-B(&jkh8`c zfb;-Bj(61%CM-q*;`#DDyeb+1&@;R3pc1%j_9ab2c)c@cLmgpj0};aH)#SI+sIU;nGenBUSpWb@IPiahGBmZKX476&_$inp z0PvtQN&;+dgnjuwYAUS@s?{q$ zPkfxi_>-T6(dV`whh4F?H#IWc2BBgM-x*wgERwUKx6T1fS~AhZAbc=5XA(I zv&7+u(4+pb#pf8^=S2SsvfVSsO2ldP-*H$)#=PG2XHlxa=t1zx z-EdR@^9J$Xf?|eKA{x0aiJgo#Oi*=0(rLL3^u0yYb4i$!)yG3fM^Hl$Nd{UgG=g8k zfxicXvEh%6k-0WUPkiVmmkucOced4G!KMPk=}SvBL&{u@sk*ASseDa31zQ@|i1mE* zYX(Wy?JU~R)U#ym6hOCRq^*hAi^^PjU%=dH6;P~ztf;bqQ4H{!ox5xuxH$lZYsARb zoz}Yr`D_f_nW~0Vj!MQ3092b+>(-(dHaS7O_8QQp)}=|9PA2rZZZoO-?`D!Jf|Ah! z0ZBor>rPXl(lXN#Qdi5PcfS~OB}}OGsvyX4O0@ws0_@rY)v0LUqtenk@MUHd!o2O`!H{5#)(ipJ(OM-+%uePtP0Hs&zU{7PZr&EiysZrU_l|9^d2fIOFsA$@+HC!`V)j{A~;1ukE75 zxyc$#U{Ru#NN0z*s;nW%MuGuoJm{PlbDnTs&Kfv~1j|~Wx&@b#HVZYZ#{>(MVQWAR zjRBys0Zd5r%m4r&07*naRGfHK^KC6ymx6WMFwHZzvYIrg45v!Llv(2lctkPial;cG zQOc$&O$%kJp@B81My;!Y5(fY%8YzoZ!{Dxp6&p^6_jovdz<2L|gKhf-MXmrQY-PgJ z6qusWPs4ZpUqaG-Wx9G% z?%enKK+uc=?TiuZP29S4HCoH}a$QOu>#%n@bji>^hM+YL5{4otocQm-RIt@QKxk|I z(Cg9v2OMy`M!oiT1;ZXnIJ}MonMTHBVEQ+FUMU68%@q~Fkpvs1vXCzKYS?zoL*xa5!1ZPTz%(5a zb5i3yK}WK-*`?=4!CJZ09ppH%Jm$ZgYo!zxA9`chD;4C|kzU^{ilm1h>rd3)d@2-Q!|RXzkrG!q+pF;kj>#{5sIMO%Tiq ze)YY^o^Fm5#=x*6p{AH{tahloev1sHXTApuo)xusGEN}5VwE54p)=)u&0B?9*=-NB z)ny;Ypyzkn_s-bI{oQ?eUApa{!6DK;#ygfD7~9y0@w;GfH|x*n&iDA+DySmh4y?pl z?cUi}=N?M<4`0?V!Omd-Q}B(o-P+m5UI-wIFt$sB5dmR;3L}7tb#WR;nC66IWt=ZY zi`rHlVXFXF+cWoEDfBU@$6Jcn(1FL^W@gv1agOOZ39f|=LWh`;B1-dZM-*GRU|lu% zn@kmJS=x9L5z3|!ROgwotXDie|AND;A>^kttNx4i^h&Sa>G1eB0Pt6LiBKsU+&{L~ zYWu^%B1bs*a{C0;X9RW4+n^BuCn2n>zFUeQXN)lb8WXpB@qY{E(^Q$HlQE@ks4{R4 z$J-(;jyGc7(m_oR-qC|-xV5wAM6n*`Kk)sBzr*9hgn#;f{}Ib|!MhJL(qsh1V%=Yt zUofR3PLB_$^Z)^2EuXO(Dkr1JBg1tMi2K)l<~&MieF%Gcx|4nk+3Os9U%;3qh8G?Q zo_&T$aMAs*y~KAbr1iB21hk+u?%UiXIIE`sz(7C0$gXU=*Y^00DeK4)Kt0BRGDouN zi0ySMvncf0wuO3d6?h)#c}pN*joFh+#NF+QZ9 z&LajQAIrfm@3w4Q^6%~QylHsW%k(Xa_73$n_Bj@Ti@_cuxYt4Gq0kq`P{eImFkD_U zXR`MK1nrrByW5Z-jd`H&oqM|W2M0CM+d|O`VSkybfAHJy_E2ORzvHC)@Rw_Cw$((0 zZ4=OZ0H+O7RvU{zV?kX*L=jen`3STvhvpIBb2PS>#y;wH0k+1PO@Pg_GGd)}M6u_G z*hj$2dBySY2$HK#w^C3IWN8~RuG=NGhJEGND_+%K-^IS^8?P^*bKlDX(1x+pigi(p_TbZ&etm1MJloFV`gNWTUl7^1&MB{@2jp&vaX}65J1LlPP z?fd_V!vXjo|M*Y%;g4r*l5kxK+p2tn8f_!2+Zm-iIrhQI~@gc^x^y~yx1ji|3N@S0E>FNQ)23~QScdS~k@K7#x@5Fa+dLRG^tzB$~ zz0bh)LfE!lFUs)J@T>{}#3+rF_osa;O8h9Hul{-~8UW%Hu#7Y4T_QmZE;#;XXXJXM ztRO=@2WsgIUJZ80;#rd;h^7fp;(L!}b#?!?2q<^>-wcvMs9>v7n4{8iX%zTYSKEnT zzXc)S-RT|by5Yb7&wqh1;lpnUIRlg}sK-Z5JRJ!0v49gnsG`&tT+cs&IpN*I0}k_y zPcP5tT8~iBP*>cn)^37!Lr-_tYXo`xPG8RC&&vCT=-y+_yK)98bTwz&fX?f=ow`bN(Vo7S4wr5hYF2ih!c?GnzZ?g+vGPY^Vsi$q(iQl`&(8kXw z-S_vrfRJyfqql2ZCDh*CA5pB#I8@rD+`F=O%zIz=#xif7?$h4W0F0#&(xDK_Q1fvS5W1@y8hZY3yPg~sBVX$A{2XZ1TLDgZz*_v+IsL| z+@+Qw9R`mepF`0g71H1He98t;-Vw$&o|bC2ex9BeHF-J!$>}xeyG#V$M;Q8wueSmK zKznNa#mfPLgvqbDh-lpDxW5GGLRvTAFlTc!d@bk5pruJnFE79*g2WwgXuho`@cpZS zf;7|_YXi8EU5&e zR9SIdenCzLeE0qxwnDfpYb*aRzv#}leTtp*e-HlOz1$LGRR7*(bi>z3uzEc5@!h!Q zEgdYZkB^Z@wxgbTXDppK4ptQd4IS&;QUy-|5z=@HIDnB+0zr$7x*_;}NBZv}iHv#N zLOg#b)+t`pvJ_`X!x9SpDS|jwp49*fU~Tn#(m~d3S{;v0(mgb=m&lOOU)1Uw)%wv+ zVc&KyhQrMrbKcdx{d@%s1RiX!-2#lZog;B>?AON)8VF2%Oxw2@jI|QraR5AiMr(tQ zwN(4s~Cvfmm9pOkF7A&7Ls3aE=p*?O=X z_v8~{>GdXFbF`X>b`;$4h+%vQc|D#`DnzE?2KtK79t);TrE-cdug8lfjA=x z(EOc6eZZL$C>>GkR6&6U`!NzoM|}Ic3Sx_Fn8Z|qjKlGO(|<9|M-g0K1Z5FCeIm?< zjMMvsl)N1RqJnpacX&9w$MYrQy1al>hhD^DM`hw5_upX4W^U$0Uo0uM*7pV-k%SnMxHG6Y4ar}b#0`ieTii1%n3{rG`gDx z|Ix5P6DS4(BK4)$xss4v)r%N(2!QCB>5O?Gn1d~YOM#g8WPA9=G~+^+`^+?(? z2z8M&fYRoF$Y}s6v(+(BM5DM$QmCXE*gnvVBzqPXH6+$f=C)@q z2pS2%z?PP$isxCs(*Z;UzETARL>epzsCLMeZ44U+R+?~V+JewTi&dpDFWQz*Xj*mV zENsSUtW+mn_6su1K%laV0A$SFaf$LE#`a8_EH^K6TFLQdRApBOnG%y!C{ zy>)I*hwiB$+WuC5Qa3=Zu(I`(3wK#mmq$iQ)CP-L<3c2^tg0Lg<`7{+6Bd8v&EJ0rIhLDeP~ zARdX1+(@vZR5oGI{8~Aolno21MSZD`qFt>>5VA*w~&birw@9U z1z4_x32DI$|jc^d!XpmG$tKz1vXym(nyzd{@$-0*57P zVbS{i*D?sN-V^WQc1O3X>$UC7#q$?9C2VQhK}ts80<#7L8Q*}VV8zE)P=pH&aKZDX zUgnT(*J^0JBs9tD)@uT3zoo0vWlSB%Cdz&7Mhl=M<1>3tf_4BRA>6f>;O|gi#9`dp z_qd@(yEHM~okQK?*2dUF4U7yebC5#T`q+&_e<}!y&uQ$&q5R%6J1N}SK1lg-t_GF8 zUp$20?GDn3M)F zzA^&hgl)6HAyPn`)jz+iNSr{4)VH)QEe!y38C*1w55_nEgbk%s6xon?!n$4oY#ODk zs@vf_9kFg#h-|2`sd`@ua+;vQi5Q6!KD_@HnOD4={|I5h)2B~3pI1;8c$i^M8HosM zIa{ctWx>;@iggp59+a^po`qKE(3a`Q9D zlN=y4qtr8CgvbTy25!5Xtgb;US8_f>z`9PPfGDA2MU@pSdbBr*pP{j8nHF=y!vU*T%>;->XoR?H zZtn-xqG(wWP2U0)5oA7~NJS}&WvNk5>k8y_ zLa7UuZ3Bx2+sg-)rkQ8;>lcH?*1tLH`j46c2qWhs*7X9|)0M1yq zRRa$J$Z0mgO&8U=07V|LmNV4TnQ%NjV7cm=AyMY90f`9ne8Re}00@~Ul(Hf50qdq~ zV_g?5LuOpB7rd40%>aNXt>`b8L;{hyYss|Frb`O`txG>pX8pPeK*&Y{A=488mm&l8 z820~R`~OjTF(xxjGrsxoJ0z|s+Y6TU7kplR0s%zuclL~r0Ua2AaAx7TX zm|j#OJOH2x9tQ!Idyy4VFPNtjP!IU@vbNbYr5RFZ3rh<;9KOS0I-yFzQa-=hU;9(Z z{^Qpx@BUd?((dywDO0d_x9gX*@zzPznHddfqr^IhUr$va` z0{`agrAuRDeloOWx32E?MK5Tm+b|uC0lfD9O_^gJcCJ?6;z4Mp?BBERqg7zP7t)WT zwyRepGhd=3U%YJGD3Al9CQQzdGBUPX{6 zLSBJuL7(fSarxI(kP6}92&BV)9JS1@Iq1MnhK}v;bUNyN*SOvEi2z{-n{XabNe{I*B0RU2~P&_0G#i8-^&J;SnS+`1#ZCQR|{d40B%?wOGA< zPxD^;so%Tt7=VN}j2*_r`1ZrMDDnxlZY@pSfXfv)pI`9tXTiJg8OINTIUn(#-v95o zuD@Wd7o;@fG(P}1qhP_hop4zNTM24z?5gw1b)T_1q3}KT+h;e-amYt@Y3|j=2-eNx z(MYYu6BrUH@m04yOA}}c56qN?nV}8qfFRL~M2`?`fn`S~F*1K6x19kv5tQ4$RQ3BF zgp8H(4Kz(V_K(QEEqD6e@5)$Kr@z`y{p9vYX-Ch2SeKF6+n;U2QFE7d;!l4 zc#zZ#06rva`GqAM z?L*?b0>br-cDPtP+PdRExdkE8ZIIe{!2}_ogOo80>Q{Ze830fLxo?`;m!lp?A>m$R zm9~_re@A<>C)GXp2|dCD!sNbp4!47Xf@uQQGln_T|Am4?TJQ}uAQW7#ANBB?7E@kB zsgxD?{0wkE2_dwnyUl2f?6EDcbkpvh;Kx6G#4mr`P(iBVOTcASj+iFG@jYRFu!SZY zmhA^D+t0`;f$55u>kq1~XJDS*cv*nw<>yyy2O^{Paq%&{4;5aw3An?|Uw!xf zv)6KtWZ-V9D45*Ie-ApeyY~b!rp|z@D7Zik^J;jP#_VP6vuO0^b#D^T4f7xCKM1Am zjuUoc8nOp3yUK(X%kJHl-k4Za_ure8KC>NCJ1dLOqjBE7bPO8v9G>3{*ehlr`{&O1 zbua#|DTOmi?{kTd_X{!rjhp9QR#+D?5}-5kXdloX^>@3ShV=d$=Dxj@~Fl_|@R&j2EJ?E;K8HamzQr8ird4!Bwt(#PujOt@SHkM992)aLpC za_}XZ;dyo;Y>5BRRiR(~^;Q6Y)U6=R0Rr4exv#z1w&{lX*i}+KDRr-mi7}-KYt^%; z+g{q;tVbxpNe|4q=LdYZYNCe{B?i`78>06ugDQm2p9Dn&^Fab0xdkEj>ekD_&{qNj zOVIcS1q)8!5jbo8rz|*DQY(K3*p5df0882MeEtZLGb*YbjoQ`Xr7S3T!kh{o<|AHK z-3v_o1=rep;N(}Y5#ZfY@;?_a+{w>fk?y4m%%&M;NelwC2cG>WjsFdGApj6T<*V9r z+%U>$7`bC|v9KUW-R_9(8S}4o`YY*#TK=!4Z6ILJ2wEKlgDc@p$qs*Z%sq_r-W?8+ zaYp9Rp5H636aLrJ{I6XU%J8)^%rBx*!nb?9GRFO4+XI6i=ahe!Fn?rtPuizX%yI4t z2-7TBuCYD{fJ^Hm)HfG~2|@QXEe3jGxvlxJ3>sc><{a12x&rCY`{0WpE@&4hR@3{& z`n3y>KozO?a{L;vw*mk_%r$Y+liZjcjx>^nHo!W#P-u`~MWflTh#!HAN3a1cUCvn8w^hFVyq_wW;>lS=NUu^+rpR+4}a4D{Iy-{dM+tjI7$iX zZbykQH@yTqFi2fOYTa!AJQ>p=lSmUZ=!#~LQU;N_8`io3Wano~v2D3(e#>mw!e(OK zTD*WH)cjP}l~F0FTD=05^*B-{z0WNQTMpK*Nf$orguku~o&cU1)nZjwYr7L75^e{c z5EV45adL*HZiihp*ZXTEhWD2w&@~8Z{arznkobhPJR!Q8g&jwTRFrbTF`qEyjOX(L zkA(mcnYL5?%rzCRq=J5b_?^PEXi zBW|(X!+zz?2&!pqTh{$~ELNmqsRherLS?}tD+usJ()Nb?9(Oxt6@f4gnu9xxI!IX~ z8@Oevy=|?8u`h;vtt}0BlYz%54HE8ZAexlt>%!7izvuZyM%$Ien!O$()B4AmU|SG~ zL)*cgOW#3T5rg!!!)3yniTua=qUBMYY1;F)AMa&^0UHbjtTjSmTqNv=Ya9ZI-;+=e zeOFJcbXo^v%$`4k*xvW!q{Una8K`yCus*yel)|`N5|Z@1bonTQT}r}n>LIJEcubYa zD(xNuT0>4#Ynggt>rucNJj@Y|1;VH{ButEL6`Y?ZfC%%X?KwLi%b$ri1j`X}&HK6GK^#+;Z0!tSBX$ms;;u1!dsG3N;>W#l~JFcFG8fk>yA1_kOw zjOhe|1|a(M3$T_)y!(xUuXo4a;KSqZQ0p@wdV1s2<==7Ls>No|fIW$i0Qd8H*rNtH z0Rn+p&oR(qsRb6&h0b6YFr);sc;-wV?8k!kkh%vlV8MZsv5>3;N|f+2&CT#>V7j12 zQ1yMFgQ>9hO38>*hByI^sR?-az4{XHGj58Z(*B7m}d1kjUNE7ViP#tm#| z5NJ>=rWutIsOp*!R9kNn#%|Kz=mY1gn2bzn(4~8q)y@J`?N!db&Kg)o_77Xv6H=Wa zT>CvyKIs60KsSMaPzBXoWSOl$fCet5_8v^>V1bJImZ1s{Y{%YaZHxQd8*pVXrkwlM zgrQ}g^rXCHwNVqafIaHJI3p!edQ50(raT8%L+kmLa4Ip0%~Wo>74ecpi`bPPX~N>_!j5uFL+)) zqKk3fXBCI(0e|=Xe+5y+x)rQf!KaUZLIGnw0@DOsufX%qz~?g{8z4o=R24=og1`H3 zfV5`1bGF>gGh+Q8~H>!~SRX)A5phTB90scBaY3^b

g^-kJGaD*{#?V6#sC4OKiT) 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

tEKlQUTt`(0%_I-P5AR%(w2)?O>3a%blspWyj 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 A$p8QV literal 0 HcmV?d00001 diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html index 6a82809b..7ecadce8 100755 --- a/data/interfaces/default/logs.html +++ b/data/interfaces/default/logs.html @@ -9,21 +9,23 @@

LogsLogs

+
+
+ +
+
+ + (Mins) +
+
- NZB.SU -
- +
+ NZB.SU
@@ -330,9 +383,8 @@
- DOGNZB -
- +
+ DOGNZB
@@ -343,20 +395,31 @@
- NZBX -
- +
+ Use Experimental Search +
+
+ Note: this is an experimental search - results may be better/worse.
- EXPERIMENTAL -
- Note: this is an experimental search - results may be better/worse. +
+ Torrents
-
- +
+
+ +
+
+ +
+
+ + +
+
@@ -374,19 +437,23 @@ %> %for newznab in config['extra_newznabs']: <% - if newznab[2] == '1' or newznab[2] == 1: + if newznab[3] == '1' or newznab[3] == 1: newznab_enabled = "checked" else: newznab_enabled = "" %>
+
+ + +
- +
- +
@@ -427,7 +494,7 @@
- +
@@ -442,7 +509,13 @@ +
+ Duplicate Handling +
+ +
+
@@ -789,7 +862,7 @@ $("#add_newznab").click(function() { var intId = $("#newznab_providers > div").size() + deletedNewznabs + 1; - var formfields = $("
"); + var formfields = $("
"); var removeButton = $("
"); removeButton.click(function() { $(this).parent().remove(); @@ -812,6 +885,12 @@ initConfigCheckbox("#usenewznab"); initConfigCheckbox("#usenzbsu"); initConfigCheckbox("#usedognzb"); + initConfigCheckbox("#enable_torrents"); + initConfigCheckbox("#torrent_local"); + initConfigCheckbox("#torrent_seedbox"); + initConfigCheckbox("#enable_torrent_search"); + initConfigCheckbox("#enable_cbt"); + initConfigCheckbox("#enable_rss"); initConfigCheckbox("#useexperimental"); initConfigCheckbox("#useraw"); initConfigCheckbox("#replace_spaces"); diff --git a/data/interfaces/default/history.html b/data/interfaces/default/history.html index ae57248a..7ae9679d 100755 --- a/data/interfaces/default/history.html +++ b/data/interfaces/default/history.html @@ -61,7 +61,11 @@
${item['DateAdded']} ${item['ComicName']} ${item['Issue_Number']}${item['Status']}${item['Status']} + %if item['Provider'] == 'ComicBT' or item['Provider'] == 'KAT': + + %endif + [retry]
-
+
+
- + %for loglevel in ['Info', 'Warning', 'Debug']: <% - if interface == mylar.INTERFACE: + if loglevel == mylar.LOG_LEVEL: selected = 'selected="selected"' else: selected = '' %> - + %endfor -
- +
+ +
diff --git a/data/interfaces/default/readlist.html b/data/interfaces/default/readlist.html index ecb92a2a..8166c3a0 100755 --- a/data/interfaces/default/readlist.html +++ b/data/interfaces/default/readlist.html @@ -70,7 +70,7 @@ %> - + @@ -111,8 +111,10 @@ "aaSorting": [] }).rowReordering({ - sURL:"/reOrder", - sRequestType: "GET" + sAjax: "reOrder", + fnAlert: function(text){ + alert("Order cannot be changed.\n" + text); + } }); resetFilters("item"); } diff --git a/data/interfaces/default/upcoming.html b/data/interfaces/default/upcoming.html index ca4178c0..5aa8a910 100755 --- a/data/interfaces/default/upcoming.html +++ b/data/interfaces/default/upcoming.html @@ -38,8 +38,16 @@ %for issue in issues: - - + + %endfor @@ -64,8 +72,8 @@ %for upcome in upcoming: - - + + diff --git a/mylar/PostProcessor.py b/mylar/PostProcessor.py index a5fd88d5..8d6a0a21 100755 --- a/mylar/PostProcessor.py +++ b/mylar/PostProcessor.py @@ -307,17 +307,21 @@ class PostProcessor(object): logger.fdebug("issueid:" + str(issueid)) sarc = nzbiss['SARC'] #use issueid to get publisher, series, year, issue number + annchk = "no" if 'annual' in nzbname.lower(): logger.info("annual detected.") annchk = "yes" - issuenzb = myDB.action("SELECT * from annuals WHERE IssueID=?", [issueid]).fetchone() + issuenzb = myDB.action("SELECT * from annuals WHERE IssueID=? AND ComicName NOT NULL", [issueid]).fetchone() else: - issuenzb = myDB.action("SELECT * from issues WHERE issueid=?", [issueid]).fetchone() + issuenzb = myDB.action("SELECT * from issues WHERE IssueID=? AND ComicName NOT NULL", [issueid]).fetchone() + if issuenzb is not None: + logger.info("issuenzb found.") if helpers.is_number(issueid): sandwich = int(issuenzb['IssueID']) else: + logger.info("issuenzb not found.") #if it's non-numeric, it contains a 'G' at the beginning indicating it's a multi-volume #using GCD data. Set sandwich to 1 so it will bypass and continue post-processing. if 'S' in issueid: @@ -418,8 +422,8 @@ class PostProcessor(object): return self.log - comicid = issuenzb['ComicID'] - issuenumOG = issuenzb['Issue_Number'] + comicid = issuenzb['ComicID'] + issuenumOG = issuenzb['Issue_Number'] if self.nzb_name == 'Manual Run': #loop through the hits here. @@ -440,10 +444,15 @@ class PostProcessor(object): extensions = ('.cbr', '.cbz') myDB = db.DBConnection() comicnzb = myDB.action("SELECT * from comics WHERE comicid=?", [comicid]).fetchone() - issuenzb = myDB.action("SELECT * from issues WHERE issueid=?", [issueid]).fetchone() + issuenzb = myDB.action("SELECT * from issues WHERE issueid=? AND comicid=? AND ComicName NOT NULL", [issueid,comicid]).fetchone() + print "issueid: " + str(issueid) + print "issuenumOG: " + str(issuenumOG) if issuenzb is None: - issuenzb = myDB.action("SELECT * from annuals WHERE issueid=?", [issueid]).fetchone() + print "chk1" + issuenzb = myDB.action("SELECT * from annuals WHERE issueid=? and comicid=?", [issueid,comicid]).fetchone() + print "chk2" annchk = "yes" + print issuenzb #issueno = str(issuenum).split('.')[0] #new CV API - removed all decimals...here we go AGAIN! issuenum = issuenzb['Issue_Number'] @@ -533,7 +542,7 @@ class PostProcessor(object): if annchk == "yes": prettycomiss = "Annual " + str(prettycomiss) - + self._log("Annual detected.") logger.fdebug("Pretty Comic Issue is : " + str(prettycomiss)) issueyear = issuenzb['IssueDate'][:4] self._log("Issue Year: " + str(issueyear), logger.DEBUG) diff --git a/mylar/__init__.py b/mylar/__init__.py index 51994852..243b528a 100755 --- a/mylar/__init__.py +++ b/mylar/__init__.py @@ -29,7 +29,7 @@ from lib.configobj import ConfigObj import cherrypy -from mylar import versioncheck, logger, version +from mylar import versioncheck, logger, version, rsscheck FULL_PATH = None PROG_DIR = None @@ -118,6 +118,7 @@ REPLACE_CHAR = None ZERO_LEVEL = False ZERO_LEVEL_N = None LOWERCASE_FILENAME = False +IGNORE_HAVETOTAL = False USE_MINSIZE = False MINSIZE = 10 USE_MAXSIZE = False @@ -223,6 +224,27 @@ BIGGIE_PUB = 55 ENABLE_META = 0 CMTAGGER_PATH = None +ENABLE_RSS = 1 +RSS_CHECKINTERVAL = 20 +RSS_LASTRUN = None + +ENABLE_TORRENTS = 0 +TORRENT_LOCAL = 0 +LOCAL_WATCHDIR = None +TORRENT_SEEDBOX = 0 +SEEDBOX_HOST = None +SEEDBOX_PORT = None +SEEDBOX_USER = None +SEEDBOX_PASS = None +SEEDBOX_WATCHDIR = None + +ENABLE_TORRENT_SEARCH = 0 +ENABLE_KAT = 0 +ENABLE_CBT = 0 +CBT_PASSKEY = None + + + def CheckSection(sec): """ Check if INI section exists, if not create it """ try: @@ -281,7 +303,9 @@ def initialize(): USE_NZBGET, NZBGET_HOST, NZBGET_PORT, NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_PRIORITY, NZBSU, NZBSU_APIKEY, DOGNZB, DOGNZB_APIKEY, NZBX,\ NEWZNAB, NEWZNAB_NAME, NEWZNAB_HOST, NEWZNAB_APIKEY, NEWZNAB_ENABLED, EXTRA_NEWZNABS, NEWZNAB_EXTRA, \ RAW, RAW_PROVIDER, RAW_USERNAME, RAW_PASSWORD, RAW_GROUPS, EXPERIMENTAL, \ - ENABLE_META, CMTAGGER_PATH, INDIE_PUB, BIGGIE_PUB, \ + ENABLE_META, CMTAGGER_PATH, INDIE_PUB, BIGGIE_PUB, IGNORE_HAVETOTAL, \ + ENABLE_TORRENTS, TORRENT_LOCAL, LOCAL_WATCHDIR, TORRENT_SEEDBOX, SEEDBOX_HOST, SEEDBOX_PORT, SEEDBOX_USER, SEEDBOX_PASS, SEEDBOX_WATCHDIR, \ + ENABLE_RSS, RSS_CHECKINTERVAL, RSS_LASTRUN, ENABLE_TORRENT_SEARCH, ENABLE_KAT, ENABLE_CBT, CBT_PASSKEY, \ PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, NMA_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_APIKEY, PUSHOVER_USERKEY, PUSHOVER_ONSNATCH, LOCMOVE, NEWCOM_DIR, FFTONEWCOM_DIR, \ PREFERRED_QUALITY, MOVE_FILES, RENAME_FILES, LOWERCASE_FILENAMES, USE_MINSIZE, MINSIZE, USE_MAXSIZE, MAXSIZE, CORRECT_METADATA, FOLDER_FORMAT, FILE_FORMAT, REPLACE_CHAR, REPLACE_SPACES, ADD_TO_CSV, CVINFO, LOG_LEVEL, POST_PROCESSING, SEARCH_DELAY, GRABBAG_DIR, READ2FILENAME, STORYARCDIR, CVURL, CVAPIFIX, \ COMIC_LOCATION, QUAL_ALTVERS, QUAL_SCANNER, QUAL_TYPE, QUAL_QUALITY, ENABLE_EXTRA_SCRIPTS, EXTRA_SCRIPTS, ENABLE_PRE_SCRIPTS, PRE_SCRIPTS, PULLNEW, COUNT_ISSUES, COUNT_HAVES, COUNT_COMICS, SYNO_FIX, CHMOD_FILE, CHMOD_DIR, ANNUALS_ON, CV_ONLY, CV_ONETIMER, WEEKFOLDER @@ -298,6 +322,7 @@ def initialize(): CheckSection('Raw') CheckSection('Experimental') CheckSection('Newznab') + CheckSection('Torrents') # Set global variables based on config file or use defaults try: HTTP_PORT = check_setting_int(CFG, 'General', 'http_port', 8090) @@ -355,6 +380,7 @@ def initialize(): ZERO_LEVEL = bool(check_setting_int(CFG, 'General', 'zero_level', 0)) ZERO_LEVEL_N = check_setting_str(CFG, 'General', 'zero_level_n', '') LOWERCASE_FILENAMES = bool(check_setting_int(CFG, 'General', 'lowercase_filenames', 0)) + IGNORE_HAVETOTAL = bool(check_setting_int(CFG, 'General', 'ignore_havetotal', 0)) SYNO_FIX = bool(check_setting_int(CFG, 'General', 'syno_fix', 0)) SEARCH_DELAY = check_setting_int(CFG, 'General', 'search_delay', 1) GRABBAG_DIR = check_setting_str(CFG, 'General', 'grabbag_dir', '') @@ -423,6 +449,25 @@ def initialize(): INDIE_PUB = check_setting_str(CFG, 'General', 'indie_pub', '75') BIGGIE_PUB = check_setting_str(CFG, 'General', 'biggie_pub', '55') + ENABLE_RSS = bool(check_setting_int(CFG, 'General', 'enable_rss', 1)) + RSS_CHECKINTERVAL = check_setting_str(CFG, 'General', 'rss_checkinterval', '20') + RSS_LASTRUN = check_setting_str(CFG, 'General', 'rss_lastrun', '') + + ENABLE_TORRENTS = bool(check_setting_int(CFG, 'Torrents', 'enable_torrents', 0)) + TORRENT_LOCAL = bool(check_setting_int(CFG, 'Torrents', 'torrent_local', 0)) + LOCAL_WATCHDIR = check_setting_str(CFG, 'Torrents', 'local_watchdir', '') + TORRENT_SEEDBOX = bool(check_setting_int(CFG, 'Torrents', 'torrent_seedbox', 0)) + SEEDBOX_HOST = check_setting_str(CFG, 'Torrents', 'seedbox_host', '') + SEEDBOX_PORT = check_setting_str(CFG, 'Torrents', 'seedbox_port', '') + SEEDBOX_USER = check_setting_str(CFG, 'Torrents', 'seedbox_user', '') + SEEDBOX_PASS = check_setting_str(CFG, 'Torrents', 'seedbox_pass', '') + SEEDBOX_WATCHDIR = check_setting_str(CFG, 'Torrents', 'seedbox_watchdir', '') + + ENABLE_TORRENT_SEARCH = bool(check_setting_int(CFG, 'Torrents', 'enable_torrent_search', 0)) + ENABLE_KAT = bool(check_setting_int(CFG, 'Torrents', 'enable_kat', 0)) + ENABLE_CBT = bool(check_setting_int(CFG, 'Torrents', 'enable_cbt', 0)) + CBT_PASSKEY = check_setting_str(CFG, 'Torrents', 'cbt_passkey', '') + USE_SABNZBD = bool(check_setting_int(CFG, 'SABnzbd', 'use_sabnzbd', 0)) SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '') SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '') @@ -469,16 +514,41 @@ def initialize(): NEWZNAB_HOST = check_setting_str(CFG, 'Newznab', 'newznab_host', '') NEWZNAB_APIKEY = check_setting_str(CFG, 'Newznab', 'newznab_apikey', '') NEWZNAB_ENABLED = bool(check_setting_int(CFG, 'Newznab', 'newznab_enabled', 1)) + NEWZNAB_NAME = NEWZNAB_HOST + if CONFIG_VERSION == '4': + NEWZNAB_NAME = check_setting_str(CFG, 'Newznab', 'newznab_name', '') + + # this gets nasty + # if configv is != 4, then the NewznabName doesn't exist so we need to create and add it and + # then rewrite + # if configv == 4, Newznab name exists and let it go through.... # Need to pack the extra newznabs back into a list of tuples flattened_newznabs = check_setting_str(CFG, 'Newznab', 'extra_newznabs', [], log=False) - EXTRA_NEWZNABS = list(itertools.izip(*[itertools.islice(flattened_newznabs, i, None, 3) for i in range(3)])) + if CONFIG_VERSION == '4': + EN_NUM = 4 #EN_NUM is the number of iterations of itertools to use + else: + EN_NUM = 3 + + EXTRA_NEWZNABS = list(itertools.izip(*[itertools.islice(flattened_newznabs, i, None, EN_NUM) for i in range(EN_NUM)])) + + #if ConfigV3 add the nzb_name to it.. + if CONFIG_VERSION != '4': + ENABS = [] + for en in EXTRA_NEWZNABS: + #set newznabname to newznab address initially so doesn't bomb. + ENABS.append((en[0], en[0], en[1], en[2])) + #now we hammer the EXTRA_NEWZNABS with the corrected version + EXTRA_NEWZNABS = ENABS + #update the configV and write the config. + CONFIG_VERSION = '4' + config_write() #to counteract the loss of the 1st newznab entry because of a switch, let's rewrite to the tuple if NEWZNAB_HOST and CONFIG_VERSION: - EXTRA_NEWZNABS.append((NEWZNAB_HOST, NEWZNAB_APIKEY, int(NEWZNAB_ENABLED))) + EXTRA_NEWZNABS.append((NEWZNAB_NAME, NEWZNAB_HOST, NEWZNAB_APIKEY, int(NEWZNAB_ENABLED))) # Need to rewrite config here and bump up config version - CONFIG_VERSION = '3' + CONFIG_VERSION = '4' config_write() # update folder formats in the config & bump up config version @@ -734,6 +804,7 @@ def config_write(): new_config['General']['zero_level'] = int(ZERO_LEVEL) new_config['General']['zero_level_n'] = ZERO_LEVEL_N new_config['General']['lowercase_filenames'] = int(LOWERCASE_FILENAMES) + new_config['General']['ignore_havetotal'] = int(IGNORE_HAVETOTAL) new_config['General']['syno_fix'] = int(SYNO_FIX) new_config['General']['search_delay'] = SEARCH_DELAY new_config['General']['grabbag_dir'] = GRABBAG_DIR @@ -761,6 +832,27 @@ def config_write(): new_config['General']['indie_pub'] = INDIE_PUB new_config['General']['biggie_pub'] = BIGGIE_PUB + new_config['General']['enable_rss'] = int(ENABLE_RSS) + new_config['General']['rss_checkinterval'] = RSS_CHECKINTERVAL + new_config['General']['rss_lastrun'] = RSS_LASTRUN + + new_config['Torrents'] = {} + new_config['Torrents']['enable_torrents'] = int(ENABLE_TORRENTS) + new_config['Torrents']['torrent_local'] = int(TORRENT_LOCAL) + new_config['Torrents']['local_watchdir'] = LOCAL_WATCHDIR + new_config['Torrents']['torrent_seedbox'] = int(TORRENT_SEEDBOX) + new_config['Torrents']['seedbox_host'] = SEEDBOX_HOST + new_config['Torrents']['seedbox_port'] = SEEDBOX_PORT + new_config['Torrents']['seedbox_user'] = SEEDBOX_USER + new_config['Torrents']['seedbox_pass'] = SEEDBOX_PASS + new_config['Torrents']['seedbox_watchdir'] = SEEDBOX_WATCHDIR + + new_config['Torrents']['enable_torrent_search'] = int(ENABLE_TORRENT_SEARCH) + new_config['Torrents']['enable_kat'] = int(ENABLE_KAT) + new_config['Torrents']['enable_cbt'] = int(ENABLE_CBT) + new_config['Torrents']['cbt_passkey'] = CBT_PASSKEY + + new_config['SABnzbd'] = {} new_config['SABnzbd']['use_sabnzbd'] = int(USE_SABNZBD) new_config['SABnzbd']['sab_host'] = SAB_HOST @@ -847,6 +939,13 @@ def start(): SCHED.add_interval_job(updater.dbUpdate, hours=48) SCHED.add_interval_job(search.searchforissue, minutes=SEARCH_INTERVAL) + + #initiate startup rss feeds for torrents/nzbs here... + SCHED.add_interval_job(rsscheck.tehMain, minutes=int(RSS_CHECKINTERVAL)) + + logger.info("Initiating startup-RSS feed checks.") + rsscheck.tehMain() + #SCHED.add_interval_job(librarysync.libraryScan, minutes=LIBRARYSCAN_INTERVAL) #weekly pull list gets messed up if it's not populated first, so let's populate it then set the scheduler. @@ -877,14 +976,16 @@ def dbcheck(): c.execute('CREATE TABLE IF NOT EXISTS comics (ComicID TEXT UNIQUE, ComicName TEXT, ComicSortName TEXT, ComicYear TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, Have INTEGER, Total INTEGER, ComicImage TEXT, ComicPublisher TEXT, ComicLocation TEXT, ComicPublished TEXT, LatestIssue TEXT, LatestDate TEXT, Description TEXT, QUALalt_vers TEXT, QUALtype TEXT, QUALscanner TEXT, QUALquality TEXT, LastUpdated TEXT, AlternateSearch TEXT, UseFuzzy TEXT, ComicVersion TEXT, SortOrder INTEGER)') c.execute('CREATE TABLE IF NOT EXISTS issues (IssueID TEXT, ComicName TEXT, IssueName TEXT, Issue_Number TEXT, DateAdded TEXT, Status TEXT, Type TEXT, ComicID, ArtworkURL Text, ReleaseDate TEXT, Location TEXT, IssueDate TEXT, Int_IssueNumber INT, ComicSize TEXT)') c.execute('CREATE TABLE IF NOT EXISTS snatched (IssueID TEXT, ComicName TEXT, Issue_Number TEXT, Size INTEGER, DateAdded TEXT, Status TEXT, FolderName TEXT, ComicID TEXT, Provider TEXT)') - c.execute('CREATE TABLE IF NOT EXISTS upcoming (ComicName TEXT, IssueNumber TEXT, ComicID TEXT, IssueID TEXT, IssueDate TEXT, Status TEXT)') + c.execute('CREATE TABLE IF NOT EXISTS upcoming (ComicName TEXT, IssueNumber TEXT, ComicID TEXT, IssueID TEXT, IssueDate TEXT, Status TEXT, DisplayComicName TEXT)') c.execute('CREATE TABLE IF NOT EXISTS nzblog (IssueID TEXT, NZBName TEXT, SARC TEXT)') c.execute('CREATE TABLE IF NOT EXISTS weekly (SHIPDATE text, PUBLISHER text, ISSUE text, COMIC VARCHAR(150), EXTRA text, STATUS text)') # c.execute('CREATE TABLE IF NOT EXISTS sablog (nzo_id TEXT, ComicName TEXT, ComicYEAR TEXT, ComicIssue TEXT, name TEXT, nzo_complete TEXT)') c.execute('CREATE TABLE IF NOT EXISTS importresults (impID TEXT, ComicName TEXT, ComicYear TEXT, Status TEXT, ImportDate TEXT, ComicFilename TEXT, ComicLocation TEXT, WatchMatch TEXT)') c.execute('CREATE TABLE IF NOT EXISTS readlist (IssueID TEXT, ComicName TEXT, Issue_Number TEXT, Status TEXT, DateAdded TEXT, Location TEXT, inCacheDir TEXT, SeriesYear TEXT, ComicID TEXT)') c.execute('CREATE TABLE IF NOT EXISTS readinglist(StoryArcID TEXT, ComicName TEXT, IssueNumber TEXT, SeriesYear TEXT, IssueYEAR TEXT, StoryArc TEXT, TotalIssues TEXT, Status TEXT, inCacheDir TEXT, Location TEXT, IssueArcID TEXT, ReadingOrder INT, IssueID TEXT)') - c.execute('CREATE TABLE IF NOT EXISTS annuals (IssueID TEXT, Issue_Number TEXT, IssueName TEXT, IssueDate TEXT, Status TEXT, ComicID TEXT, GCDComicID TEXT, Location TEXT, ComicSize TEXT, Int_IssueNumber INT)') + c.execute('CREATE TABLE IF NOT EXISTS annuals (IssueID TEXT, Issue_Number TEXT, IssueName TEXT, IssueDate TEXT, Status TEXT, ComicID TEXT, GCDComicID TEXT, Location TEXT, ComicSize TEXT, Int_IssueNumber INT, ComicName TEXT)') + c.execute('CREATE TABLE IF NOT EXISTS rssdb (Title TEXT UNIQUE, Link TEXT, Pubdate TEXT, Site TEXT, Size TEXT)') + conn.commit c.close #new @@ -1030,11 +1131,28 @@ def dbcheck(): except: c.execute('ALTER TABLE annuals ADD COLUMN Int_IssueNumber INT') + try: + c.execute('SELECT ComicName from annuals') + annual_update = "no" + except: + c.execute('ALTER TABLE annuals ADD COLUMN ComicName TEXT') + annual_update = "yes" + + if annual_update == "yes": + logger.info("Updating Annuals table for new fields - one-time update.") + helpers.annual_update() + try: c.execute('SELECT Provider from snatched') except: c.execute('ALTER TABLE snatched ADD COLUMN Provider TEXT') + try: + c.execute('SELECT DisplayComicName from upcoming') + except: + c.execute('ALTER TABLE upcoming ADD COLUMN DisplayComicName TEXT') + + #if it's prior to Wednesday, the issue counts will be inflated by one as the online db's everywhere #prepare for the next 'new' release of a series. It's caught in updater.py, so let's just store the #value in the sql so we can display it in the details screen for everyone to wonder at. diff --git a/mylar/cmtagmylar.py b/mylar/cmtagmylar.py index 373b850d..bb033ac5 100644 --- a/mylar/cmtagmylar.py +++ b/mylar/cmtagmylar.py @@ -7,6 +7,7 @@ import sys import glob import platform import shutil +import time import zipfile import subprocess import mylar @@ -14,36 +15,42 @@ import mylar from mylar import logger def run (dirName, nzbName=None, issueid=None, manual=None, filename=None): - #print "manual:" + manual - #print "filename: " + filename logger.fdebug("dirName:" + dirName) - #print "issueid:" + issueid ## Set the directory in which comictagger and other external commands are located - IMPORTANT - ## # ( User may have to modify, depending on their setup, but these are some guesses for now ) - #check for dependencies here - configparser - try: - import configparser - except ImportError: - logger.fdebug("configparser not found on system. Please install manually in order to write metadata") - logger.fdebug("continuing with PostProcessing, but I'm not using metadata.") - return "fail" - if platform.system() == "Windows": (x, y) = platform.architecture() if x == "64bit": comictagger_cmd = os.path.join(mylar.CMTAGGER_PATH, 'comictagger.exe') - # http://www.win-rar.com/download.html else: comictagger_cmd = os.path.join(mylar.CMTAGGER_PATH, 'comictagger.exe') unrar_cmd = "C:\Program Files\WinRAR\UnRAR.exe" + + # test for UnRAR + if not os.path.isfile(unrar_cmd): + unrar_cmd = "C:\Program Files (x86)\WinRAR\UnRAR.exe" + if not os.path.isfile(unrar_cmd): + logger.fdebug("Unable to locate UnRAR.exe - make sure it's installed.") + logger.fdebug("Aborting meta-tagging.") + return "fail" + elif platform.system() == "Darwin": #Mac OS X comictagger_cmd = os.path.join(mylar.CMTAGGER_PATH) unrar_cmd = "/usr/local/bin/unrar" else: + #for the 'nix + #check for dependencies here - configparser + try: + import configparser + except ImportError: + logger.fdebug("configparser not found on system. Please install manually in order to write metadata") + logger.fdebug("continuing with PostProcessing, but I'm not using metadata.") + return "fail" + #set this to the lib path (ie. '/lib') comictagger_cmd = os.path.join(mylar.CMTAGGER_PATH, 'comictagger.py') unrar_cmd = "/usr/bin/unrar" @@ -179,15 +186,16 @@ def run (dirName, nzbName=None, issueid=None, manual=None, filename=None): if filename.endswith('.cbz'): f = os.path.join( comicpath, filename ) - try: - rar_test_cmd_output = "is not RAR archive" #default, in case of error - rar_test_cmd_output = subprocess.check_output( [ unrar_cmd, "t", f ] ) - except: - pass - if not "is not RAR archive" in rar_test_cmd_output: - base = os.path.splitext( f )[0] - shutil.move( f, base + ".cbr" ) - logger.fdebug("{0}: renaming {1} to be a cbr".format( scriptname, os.path.basename( f ) )) + if os.path.isfile( f ): + try: + rar_test_cmd_output = "is not RAR archive" #default, in case of error + rar_test_cmd_output = subprocess.check_output( [ unrar_cmd, "t", f ] ) + except: + pass + if not "is not RAR archive" in rar_test_cmd_output: + base = os.path.splitext( f )[0] + shutil.move( f, base + ".cbr" ) + logger.fdebug("{0}: renaming {1} to be a cbr".format( scriptname, os.path.basename( f ) )) # Now rename all CBR files to RAR if filename.endswith('.cbr'): @@ -219,7 +227,7 @@ def run (dirName, nzbName=None, issueid=None, manual=None, filename=None): ## Changes zip to cbz f = os.path.join( comicpath, os.path.splitext(filename)[0] + ".zip" ) - print f + print "zipfile" + f try: with open(f): pass except: @@ -231,7 +239,12 @@ def run (dirName, nzbName=None, issueid=None, manual=None, filename=None): else: nfilename = filename - file_dir, file_n = os.path.split(nfilename) + if os.path.isfile( nfilename): + file_dir, file_n = os.path.split(nfilename) + else: + #remove the IssueID from the path + file_dir = re.sub(issueid, '', comicpath) + file_n = os.path.split(nfilename)[1] logger.fdebug("converted directory: " + str(file_dir)) logger.fdebug("converted filename: " + str(file_n)) logger.fdebug("destination path: " + os.path.join(dirName,file_n)) @@ -249,7 +262,19 @@ def run (dirName, nzbName=None, issueid=None, manual=None, filename=None): logger.fdebug("Unable to move - file already exists.") else: shutil.move( nfilename, os.path.join(os.path.abspath(dirName),file_n)) - shutil.rmtree( comicpath ) + logger.fdebug("Sucessfully moved file from temporary path.") + i = 0 + + while i < 10: + try: + shutil.rmtree( comicpath ) + except: + time.sleep(.1) + else: + return os.path.join(os.path.abspath(dirName), file_n) + i+=1 + + logger.fdebug("Failed to remove temporary path : " + str(comicpath)) return os.path.join(os.path.abspath(dirName),file_n) diff --git a/mylar/filechecker.py b/mylar/filechecker.py index 9ba63d6c..acdbbbf7 100755 --- a/mylar/filechecker.py +++ b/mylar/filechecker.py @@ -57,6 +57,7 @@ def listFiles(dir,watchcomic,AlternateSearch=None): for item in os.listdir(basedir): + if item == 'cover.jpg' or item == 'cvinfo': continue #print item #subname = os.path.join(basedir, item) subname = item @@ -104,6 +105,8 @@ def listFiles(dir,watchcomic,AlternateSearch=None): logger.fdebug("possible negative issue detected.") nonocount = nonocount + subcnt - 1 detneg = "yes" + if '-' in watchcomic and i < len(watchcomic): + logger.fdebug("- appears in series title.") i+=1 if detneg == "no": subname = re.sub(str(nono), ' ', subname) @@ -131,25 +134,42 @@ def listFiles(dir,watchcomic,AlternateSearch=None): #subname = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\+\'\?\@]',' ', subname) modwatchcomic = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\'\?\@]', ' ', u_watchcomic) detectand = False + detectthe = False modwatchcomic = re.sub('\&', ' and ', modwatchcomic) + if ' the ' in modwatchcomic.lower(): + modwatchcomic = re.sub("\\bthe\\b", "", modwatchcomic.lower()) + logger.fdebug("new modwatchcomic: " + str(modwatchcomic)) + detectthe = True modwatchcomic = re.sub('\s+', ' ', str(modwatchcomic)).strip() if '&' in subname: subname = re.sub('\&', ' and ', subname) detectand = True + if ' the ' in subname.lower(): + subname = re.sub("\\bthe\\b", "", subname.lower()) + detectthe = True subname = re.sub('\s+', ' ', str(subname)).strip() + + AS_Alt = [] if AlternateSearch is not None: - #same = encode. - u_altsearchcomic = AlternateSearch.encode('ascii', 'ignore').strip() - altsearchcomic = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\+\'\?\@]', ' ', u_altsearchcomic) - altseachcomic = re.sub('\&', ' and ', altsearchcomic) - altsearchcomic = re.sub('\s+', ' ', str(altsearchcomic)).strip() + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + #same = encode. + u_altsearchcomic = AS_Alternate.encode('ascii', 'ignore').strip() + altsearchcomic = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\+\'\?\@]', ' ', u_altsearchcomic) + altseachcomic = re.sub('\&', ' and ', altsearchcomic) + altsearchcomic = re.sub('\s+', ' ', str(altsearchcomic)).strip() + AS_Alt.append(altsearchcomic) else: #create random characters so it will never match. altsearchcomic = "127372873872871091383 abdkhjhskjhkjdhakajhf" + AS_Alt.append(altsearchcomic) #if '_' in subname: # subname = subname.replace('_', ' ') logger.fdebug("watchcomic:" + str(modwatchcomic) + " ..comparing to found file: " + str(subname)) - if modwatchcomic.lower() in subname.lower() or altsearchcomic.lower() in subname.lower(): + if modwatchcomic.lower() in subname.lower() or any(x in subname.lower() for x in AS_Alt):#altsearchcomic.lower() in subname.lower(): comicpath = os.path.join(basedir, item) logger.fdebug( modwatchcomic + " - watchlist match on : " + comicpath) comicsize = os.path.getsize(comicpath) @@ -160,52 +180,55 @@ def listFiles(dir,watchcomic,AlternateSearch=None): if 'annual' in subname.lower(): logger.fdebug("Annual detected - proceeding") jtd_len = subname.lower().find('annual') + cchk = modwatchcomic else: if modwatchcomic.lower() in subname.lower(): - logger.fdebug("we should remove " + str(nonocount) + " characters") + cchk = modwatchcomic + else: + cchk_ls = [x for x in AS_Alt if x in subname.lower()] + cchk = cchk_ls[0] + #print "something: " + str(cchk) - findtitlepos = subname.find('-') - if charpos != 0: - logger.fdebug("detected " + str(len(charpos)) + " special characters") - i=0 - while (i < len(charpos)): - for i,j in enumerate(charpos): - #print i,j - #print subname - #print "digitchk: " + str(subname[j:]) - if j >= len(subname): - logger.fdebug("end reached. ignoring remainder.") - break - elif subname[j:] == '-': - if i <= len(subname) and subname[i+1].isdigit(): - logger.fdebug("negative issue detected.") - #detneg = "yes" - elif j > findtitlepos: - if subname[j:] == '#': - if subname[i+1].isdigit(): - logger.fdebug("# detected denoting issue#, ignoring.") - else: - nonocount-=1 - else: - logger.fdebug("special character appears outside of title - ignoring @ position: " + str(charpos[i])) + logger.fdebug("we should remove " + str(nonocount) + " characters") + + findtitlepos = subname.find('-') + if charpos != 0: + logger.fdebug("detected " + str(len(charpos)) + " special characters") + i=0 + while (i < len(charpos)): + for i,j in enumerate(charpos): + #print i,j + #print subname + #print "digitchk: " + str(subname[j:]) + if j >= len(subname): + logger.fdebug("end reached. ignoring remainder.") + break + elif subname[j:] == '-': + if i <= len(subname) and subname[i+1].isdigit(): + logger.fdebug("negative issue detected.") + #detneg = "yes" + elif j > findtitlepos: + if subname[j:] == '#': + if subname[i+1].isdigit(): + logger.fdebug("# detected denoting issue#, ignoring.") + else: nonocount-=1 - i+=1 + elif '-' in watchcomic and i < len(watchcomic): + logger.fdebug("- appears in series title, ignoring.") + else: + logger.fdebug("special character appears outside of title - ignoring @ position: " + str(charpos[i])) + nonocount-=1 + i+=1 - #remove versioning here - if volrem != None: - jtd_len = len(modwatchcomic) + len(volrem) + nonocount + 1 #1 is to account for space btwn comic and vol # - else: - jtd_len = len(modwatchcomic) + nonocount - if detectand: - jtd_len = jtd_len - 2 # char substitution diff between & and 'and' = 2 chars - elif altsearchcomic.lower() in subname.lower(): - #remove versioning here - if volrem != None: - jtd_len = len(altsearchcomic) + len(volrem) + nonocount + 1 - else: - jtd_len = len(altsearchcomic) + nonocount - if detectand: - jtd_len = jtd_len - 2 + #remove versioning here + if volrem != None: + jtd_len = len(cchk) + len(volrem) + nonocount + 1 #1 is to account for space btwn comic and vol # + else: + jtd_len = len(cchk) + nonocount + if detectand: + jtd_len = jtd_len - 2 # char substitution diff between & and 'and' = 2 chars + if detectthe: + jtd_len = jtd_len - 3 # char subsitiution diff between 'the' and '' = 3 chars justthedigits = item[jtd_len:] diff --git a/mylar/findcomicfeed.py b/mylar/findcomicfeed.py index 70ef48d5..cfd0c5c8 100755 --- a/mylar/findcomicfeed.py +++ b/mylar/findcomicfeed.py @@ -81,7 +81,7 @@ def Startit(searchName, searchIssue, searchYear, ComicVersion): except_list=['releases', 'gold line', 'distribution', '0-day', '0 day'] for title, link in keyPair.items(): - logger.fdebug("titlesplit: " + str(title.split("\""))) + #logger.fdebug("titlesplit: " + str(title.split("\""))) splitTitle = title.split("\"") for subs in splitTitle: diff --git a/mylar/ftpsshup.py b/mylar/ftpsshup.py new file mode 100644 index 00000000..0cc54b00 --- /dev/null +++ b/mylar/ftpsshup.py @@ -0,0 +1,48 @@ +#!/usr/local/bin/python + +#import paramiko +import os + +import mylar +from mylar import logger + +def putfile(localpath,file): #localpath=full path to .torrent (including filename), file=filename of torrent + + try: + import paramiko + except ImportError: + logger.fdebug("paramiko not found on system. Please install manually in order to use seedbox option") + logger.fdebug("get it at https://github.com/paramiko/paramiko") + logger.fdebug("to install: python setup.py install") + logger.fdebug("aborting send.") + return "fail" + + host = mylar.SEEDBOX_HOST + port = int(mylar.SEEDBOX_PORT) #this is usually 22 + transport = paramiko.Transport((host, port)) + + logger.fdebug("Sending file: " + str(file)) + logger.fdebug("destination: " + str(host)) + logger.fdebug("Using SSH port : " + str(port)) + password = mylar.SEEDBOX_PASS + username = mylar.SEEDBOX_USER + transport.connect(username = username, password = password) + + sftp = paramiko.SFTPClient.from_transport(transport) + + import sys + if file[-7:] != "torrent": + file += ".torrent" + rempath = os.path.join(mylar.SEEDBOX_WATCHDIR, file) #this will default to the OS running mylar for slashes. + logger.fdebug("remote path set to " + str(rempath)) + logger.fdebug("local path set to " + str(localpath)) + sftp.put(localpath, rempath) + + sftp.close() + transport.close() + logger.fdebug("Upload complete to seedbox.") + return "pass" + +if __name__ == '__main__': + putfile(sys.argv[1]) + diff --git a/mylar/helpers.py b/mylar/helpers.py index d635dc9f..5ee8a589 100755 --- a/mylar/helpers.py +++ b/mylar/helpers.py @@ -17,6 +17,7 @@ import time from operator import itemgetter import datetime import re +import platform import itertools import os import mylar @@ -239,7 +240,7 @@ def decimal_issue(iss): return deciss, dec_except def rename_param(comicid, comicname, issue, ofilename, comicyear=None, issueid=None): - from mylar import db, logger + import db, logger myDB = db.DBConnection() print ("comicid: " + str(comicid)) print ("issue#: " + str(issue)) @@ -684,3 +685,53 @@ def checkthepub(ComicID): logger.fdebug("Indie publisher detected - " + str(pubchk['ComicPublisher'])) return mylar.INDIE_PUB + +def annual_update(): + import db, logger + myDB = db.DBConnection() + annuallist = myDB.action('SELECT * FROM annuals') + if annuallist is None: + logger.info("no annuals to update.") + return + + cnames = [] + #populate the ComicName field with the corresponding series name from the comics table. + for ann in annuallist: + coms = myDB.action('SELECT * FROM comics WHERE ComicID=?', [ann['ComicID']]).fetchone() + cnames.append({'ComicID': ann['ComicID'], + 'ComicName': coms['ComicName'] + }) + + #write in a seperate loop to avoid db locks + i=0 + for cns in cnames: + ctrlVal = {"ComicID": cns['ComicID']} + newVal = {"ComicName": cns['ComicName']} + myDB.upsert("annuals", newVal, ctrlVal) + i+=1 + + logger.info(str(i) + " series have been updated in the annuals table.") + return + +def replacetheslash(data): + import logger + # this is necessary for the cache directory to display properly in IE/FF. + # os.path.join will pipe in the '\' in windows, which won't resolve + # when viewing through cherrypy - so convert it and viola. + if platform.system() == "Windows": + slashreplaced = replace.data('\\', '/') + else: + slashreplaced = data + return slashreplaced + +def urlretrieve(urlfile, fpath): + chunk = 4096 + f = open(fpath, "w") + while 1: + data = urlfile.read(chunk) + if not data: + print "done." + break + f.write(data) + print "Read %s bytes"%len(data) + diff --git a/mylar/importer.py b/mylar/importer.py index c11d075b..895dd5a8 100755 --- a/mylar/importer.py +++ b/mylar/importer.py @@ -218,6 +218,7 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None): "IssueDate": issdate, "IssueName": issname, "ComicID": comicid, + "ComicName": comic['ComicName'], "Status": "Skipped"} myDB.upsert("annuals", newVals, newCtrl) n+=1 @@ -356,7 +357,8 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None): urllib.urlretrieve(str(comic['ComicImage']), str(coverfile)) try: with open(str(coverfile)) as f: - ComicImage = os.path.join('cache',str(comicid) + ".jpg") + PRComicImage = os.path.join('cache',str(comicid) + ".jpg") + ComicImage = helpers.replacetheslash(PRComicImage) #this is for Firefox when outside the LAN...it works, but I don't know how to implement it #without breaking the normal flow for inside the LAN (above) @@ -740,9 +742,9 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None): # lets' check the pullist for anything at this time as well since we're here. # do this for only Present comics.... if mylar.AUTOWANT_UPCOMING and lastpubdate == 'Present': #and 'Present' in gcdinfo['resultPublished']: - print ("latestissue: #" + str(latestiss)) + logger.fdebug("latestissue: #" + str(latestiss)) chkstats = myDB.action("SELECT * FROM issues WHERE ComicID=? AND Issue_Number=?", [comicid,str(latestiss)]).fetchone() - print chkstats['Status'] + logger.fdebug(chkstats['Status']) if chkstats['Status'] == 'Skipped' or chkstats['Status'] == 'Wanted' or chkstats['Status'] == 'Snatched': logger.info(u"Checking this week's pullist for new issues of " + comic['ComicName']) updater.newpullcheck(comic['ComicName'], comicid) @@ -754,8 +756,8 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None): logger.info(u"Attempting to grab wanted issues for : " + comic['ComicName']) for result in results: - print "Searching for : " + str(result['Issue_Number']) - print "Status of : " + str(result['Status']) + logger.fdebug("Searching for : " + str(result['Issue_Number'])) + logger.fdebug("Status of : " + str(result['Status'])) search.searchforissue(result['IssueID']) else: logger.info(u"No issues marked as wanted for " + comic['ComicName']) diff --git a/mylar/rsscheck.py b/mylar/rsscheck.py new file mode 100755 index 00000000..42f4ca79 --- /dev/null +++ b/mylar/rsscheck.py @@ -0,0 +1,519 @@ +#!/usr/bin/python + +import os, sys +import re +import lib.feedparser as feedparser +import feedparser +import urllib2 +import ftpsshup +import datetime + +import mylar +from mylar import db, logger, ftpsshup, helpers + +def tehMain(): + logger.info("RSS Feed Check was last run at : " + str(mylar.RSS_LASTRUN)) + firstrun = "no" + #check the last run of rss to make sure it's not hammering. + if mylar.RSS_LASTRUN is None or mylar.RSS_LASTRUN == '' or mylar.RSS_LASTRUN == '0': + logger.info("RSS Feed Check First Ever Run.") + firstrun = "yes" + mins = 0 + else: + c_obj_date = datetime.datetime.strptime(mylar.RSS_LASTRUN, "%Y-%m-%d %H:%M:%S") + n_date = datetime.datetime.now() + absdiff = abs(n_date - c_obj_date) + mins = (absdiff.days * 24 * 60 * 60 + absdiff.seconds) / 60.0 #3600 is for hours. + + if firstrun == "no" and mins < int(mylar.RSS_CHECKINTERVAL): + logger.fdebug("RSS Check has taken place less than the threshold - not initiating at this time.") + return + + mylar.RSS_LASTRUN = helpers.now() + logger.fdebug("Updating RSS Run time to : " + str(mylar.RSS_LASTRUN)) + mylar.config_write() + + #function for looping through nzbs/torrent feeds + if mylar.ENABLE_TORRENTS: + logger.fdebug("[RSS] Initiating Torrent RSS Check.") + if mylar.ENABLE_KAT: + logger.fdebug("[RSS] Initiating Torrent RSS Feed Check on KAT.") + torrents(pickfeed='3') + if mylar.ENABLE_CBT: + logger.fdebug("[RSS] Initiating Torrent RSS Feed Check on CBT.") + torrents(pickfeed='1') + torrents(pickfeed='4') + logger.fdebug("[RSS] Initiating RSS Feed Check for NZB Providers.") + nzbs() + logger.fdebug("[RSS] RSS Feed Check/Update Complete") + logger.fdebug("[RSS] Watchlist Check for new Releases") + #if mylar.ENABLE_TORRENTS: + # if mylar.ENABLE_KAT: + # search.searchforissue(rsscheck='yes') + # if mylar.ENABLE_CBT: + mylar.search.searchforissue(rsscheck='yes') + #nzbcheck here + #nzbs(rsscheck='yes') + logger.fdebug("[RSS] Watchlist Check complete.") + return + +def torrents(pickfeed=None): + if pickfeed is None: + pickfeed = 1 + #else: + # print "pickfeed is " + str(pickfeed) + passkey = mylar.CBT_PASSKEY + if pickfeed == "1": # comicbt rss feed based on followlist + feed = "http://comicbt.com/rss.php?action=browse&passkey=" + str(passkey) + "&type=dl" + elif pickfeed == "2": # kat.ph search + feed = "http://kat.ph/usearch/" + str(seriesname) + "%20category%3Acomics%20seeds%3A1/?rss=1" + elif pickfeed == "3": # kat.ph rss feed + feed = "http://kat.ph/usearch/category%3Acomics%20seeds%3A1/?rss=1" + elif pickfeed == "4": #comicbt follow link + feed = "http://comicbt.com/rss.php?action=follow&passkey=" + str(passkey) + "&type=dl" + elif pickfeed == "5": # comicbt series link +# seriespage = "http://comicbt.com/series.php?passkey=" + str(passkey) + feed = "http://comicbt.com/rss.php?action=series&series=" + str(seriesno) + "&passkey=" + str(passkey) + else: + logger.error("invalid pickfeed denoted...") + return + logger.fdebug("feed #" + str(pickfeed) + " chosen: " + str(feed)) + title = [] + link = [] + description = [] + seriestitle = [] + + if pickfeed == "5": # we need to get the series # first + seriesSearch(seriespage, seriesname) + feedme = feedparser.parse(feed) + i = 0 + + feeddata = [] + + myDB = db.DBConnection() + + for entry in feedme['entries']: + if pickfeed == "2" or pickfeed == "3": + tmpsz = feedme.entries[i].enclosures[0] + feeddata.append({ + 'Site': 'KAT', + 'Title': feedme.entries[i].title, + 'Link': tmpsz['url'], + 'Pubdate': feedme.entries[i].updated, + 'Size': tmpsz['length'] + }) + + #print ("Site: KAT") + #print ("Title: " + str(feeddata[i]['Title'])) + #print ("Link: " + str(feeddata[i]['Link'])) + #print ("pubdate: " + str(feeddata[i]['Pubdate'])) + + elif pickfeed == "1" or pickfeed == "4": +# tmpsz = feedme.entries[i].enclosures[0] + feeddata.append({ + 'Site': 'comicBT', + 'Title': feedme.entries[i].title, + 'Link': feedme.entries[i].link, + 'Pubdate': feedme.entries[i].updated +# 'Size': tmpsz['length'] + }) + #print ("Site: ComicBT") + #print ("Title: " + str(feeddata[i]['Title'])) + #print ("Link: " + str(feeddata[i]['Link'])) + #print ("pubdate: " + str(feeddata[i]['Pubdate'])) + i+=1 + logger.fdebug("there were " + str(i) + " results..") + rssdbupdate(feeddata,i,'torrent') + return + +def nzbs(provider=None): + nzbprovider = [] + nzbp = 0 + if mylar.NZBSU == 1: + nzbprovider.append('nzb.su') + nzbp+=1 + if mylar.DOGNZB == 1: + nzbprovider.append('dognzb') + nzbp+=1 + # -------- + # Xperimental + if mylar.EXPERIMENTAL == 1: + nzbprovider.append('experimental') + nzbp+=1 + + newznabs = 0 + + newznab_hosts = [] + + if mylar.NEWZNAB == 1: + + for newznab_host in mylar.EXTRA_NEWZNABS: + if newznab_host[3] == '1' or newznab_host[3] == 1: + newznab_hosts.append(newznab_host) + nzbprovider.append('newznab') + newznabs+=1 + logger.fdebug("newznab name:" + str(newznab_host[0]) + " - enabled: " + str(newznab_host[3])) + + # -------- + providercount = int(nzbp + newznabs) + logger.fdebug("there are : " + str(providercount) + " RSS search providers you have enabled.") + nzbpr = providercount - 1 + if nzbpr < 0: + nzbpr == 0 + + feeddata = [] + feedthis = [] + ft = 0 + totNum = 0 + nonexp = "no" + + while (nzbpr >= 0 ): + if nzbprovider[nzbpr] == 'experimental': + feed = feedparser.parse("http://nzbindex.nl/rss/alt.binaries.comics.dcp/?sort=agedesc&max=50&more=1") + + totNum = len(feed.entries) + site = 'experimental' + keyPair = {} + regList = [] + entries = [] + mres = {} + countUp = 0 + + i = 0 + for entry in feed['entries']: + tmpsz = feed.entries[i].enclosures[0] + feeddata.append({ + 'Site': site, + 'Title': feed.entries[i].title, + 'Link': feed.entries[i].link, + 'Pubdate': feed.entries[i].updated, + 'Size': tmpsz['length'] + }) +# print ("Site:" + str(site)) +# print ("Title:" + str(feed.entries[i].title)) +# print ("Link:" + str(feed.entries[i].link)) +# print ("Pubdate:" + str(feed.entries[i].updated)) +# print ("Size:" + str(tmpsz['length'])) + i+=1 + logger.info(str(i) + " results from Experimental feed indexed.") + else: + if nzbprovider[nzbpr] == 'newznab': + for newznab_host in newznab_hosts: + feed = newznab_host[1].rstrip() + "/rss?t=7030&dl=1&i=1&r=" + newznab_host[2].rstrip() + feedme = feedparser.parse(feed) + site = newznab_host[0].rstrip() + feedthis.append({"feed": feedme, + "site": site}) + totNum+=len(feedme.entries) + ft+=1 + nonexp = "yes" + elif nzbprovider[nzbpr] == 'nzb.su': + feed = 'http://nzb.su/rss?t=7030&dl=1&i=1&r=' + mylar.NZBSU_APIKEY + feedme = feedparser.parse(feed) + site = nzbprovider[nzbpr] + feedthis.append({"feed": feedme, + "site": site }) + totNum+=len(feedme.entries) + ft+=1 + nonexp = "yes" + elif nzbprovider[nzbpr] == 'dognzb': + feed = 'http://dognzb.cr/rss?t=7030&dl=1&i=1&r=' + mylar.DOGNZB_APIKEY + feedme = feedparser.parser(feed) + site = nzbprovider[nzbpr] + ft+=1 + nonexp = "yes" + feedthis.append({"feed": feedme, + "site": site }) + totNum+=len(feedme.entries) + + nzbpr-=1 + + i = 0 + if nonexp == "yes": + #print str(ft) + " sites checked. There are " + str(totNum) + " entries to be updated." + #print feedme + #i = 0 + + for ft in feedthis: + site = ft['site'] + #print str(site) + " now being updated..." + for entry in ft['feed'].entries: + #print "entry: " + str(entry) + tmpsz = entry.enclosures[0] + feeddata.append({ + 'Site': site, + 'Title': entry.title, + 'Link': entry.link, + 'Pubdate': entry.updated, + 'Size': tmpsz['length'] + }) + +# print ("Site: " + str(feeddata[i]['Site'])) +# print ("Title: " + str(feeddata[i]['Title'])) +# print ("Link: " + str(feeddata[i]['Link'])) +# print ("pubdate: " + str(feeddata[i]['Pubdate'])) +# print ("size: " + str(feeddata[i]['Size'])) + i+=1 + logger.info(str(site) + " : " + str(i) + " entries indexed.") + + rssdbupdate(feeddata,i,'usenet') + return + +def rssdbupdate(feeddata,i,type): + rsschktime = 15 + myDB = db.DBConnection() + + #let's add the entries into the db so as to save on searches + #also to build up the ID's ;) + x = 1 + while x <= i: + try: + dataval = feeddata[x] + except IndexError: + logger.fdebug("reached the end of populating. Exiting the process.") + break + #print "populating : " + str(dataval) + #remove passkey so it doesn't end up in db + if type == 'torrent': + newlink = dataval['Link'][:(dataval['Link'].find('&passkey'))] + newVal = {"Link": newlink, + "Pubdate": dataval['Pubdate'], + "Site": dataval['Site']} + else: + newlink = dataval['Link'] + newVal = {"Link": newlink, + "Pubdate": dataval['Pubdate'], + "Site": dataval['Site'], + "Size": dataval['Size']} + + ctrlVal = {"Title": dataval['Title']} + + myDB.upsert("rssdb", newVal,ctrlVal) + + x+=1 + + logger.fdebug("Completed adding new data to RSS DB. Next add in " + str(mylar.RSS_CHECKINTERVAL) + " minutes") + return + +def torrentdbsearch(seriesname,issue,comicid=None): + myDB = db.DBConnection() + seriesname_alt = None + if comicid is None or comicid == 'None': + pass + else: + snm = myDB.action("SELECT * FROM comics WHERE comicid=?", [comicid]).fetchone() + if snm is None: + logger.fdebug("Invalid ComicID of " + str(comicid) + ". Aborting search.") + return + else: + seriesname = snm['ComicName'] + seriesname_alt = snm['AlternateSearch'] + + + tsearch_seriesname = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.\s]', '%',seriesname) + formatrem_seriesname = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.]', '',seriesname) + if formatrem_seriesname[:1] == ' ': formatrem_seriesname = formatrem_seriesname[1:] + tsearch = tsearch_seriesname + "%" + #print tsearch + if mylar.ENABLE_CBT: + tresults = myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site='comicBT'", [tsearch]) + if mylar.ENABLE_KAT: + tresults += myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site='KAT'", [tsearch]) + if tresults is None: + logger.fdebug("torrent search returned no results for " + seriesname) + if seriesname_alt is None: + logger.fdebug("no Alternate name given. Aborting search.") + return "no results" + else: + chkthealt = seriesname_alt.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + if mylar.ENABLE_CBT: + tresults += myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site='comicBT'", [AS_Alternate]) + if mylar.ENABLE_KAT: + tresults += myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site='KAT'", [AS_Alternate]) + if tresults is None: + logger.fdebug("torrent alternate name search returned no results.") + return "no results" + extensions = ('cbr', 'cbz') + tortheinfo = [] + torinfo = {} + + for tor in tresults: + torsplit = tor['Title'].split('/') + #print tor['Title'] + #print ("there are " + str(len(torsplit)) + " sections in this title") + i=0 + #0 holds the title/issue and format-type. + while (i < len(torsplit)): + #print "section(" + str(i) + "): " + str(torsplit[i]) + i+=1 + formatrem_torsplit = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.\-]', '',torsplit[0]).lower() + formatrem_torsplit = re.sub('\s+', ' ', formatrem_torsplit) + #print (str(len(formatrem_torsplit)) + " - formatrem_torsplit : " + formatrem_torsplit.lower()) + #print (str(len(formatrem_seriesname)) + " - formatrem_seriesname :" + formatrem_seriesname.lower()) + if formatrem_seriesname.lower() in formatrem_torsplit.lower(): + logger.fdebug("matched to : " + tor['Title']) + logger.fdebug("matched on series title: " + seriesname) + titleend = formatrem_torsplit[len(formatrem_seriesname):] + titleend = re.sub('\-', '', titleend) #remove the '-' which is unnecessary + + titleend = re.sub('cbr', '', str(titleend)) #remove extensions + logger.fdebug("titleend: " + str(titleend)) + sptitle = titleend.split() + extra = '' + for sp in sptitle: + if 'v' in sp.lower() and sp[2:].isdigit(): + volumeadd = sp + elif 'vol' in sp.lower() and sp[3:].isdigit(): + volumeadd = sp + if sp.isdigit(): + #print("issue # detected : " + str(issue)) + if int(issue) == int(sp): + logger.fdebug("Issue matched for : " + str(issue)) + #the title on CBT has a mix-mash of crap...ignore everything after cbz/cbr to cleanit + ctitle = tor['Title'].find('cbr') + if ctitle == 0: + ctitle = tor['Title'].find('cbz') + if ctitle == 0: + logger.fdebug("cannot determine title properly - ignoring for now.") + continue + cttitle = tor['Title'][:ctitle] + #print("change title to : " + str(cttitle)) + + if extra == '': + tortheinfo.append({ + 'title': cttitle, #tor['Title'], + 'link': tor['Link'], + 'pubdate': tor['Pubdate'], + 'site': tor['Site'], + 'length': tor['Size'] + }) + continue + #torsend2client(formatrem_seriesname,tor['Link']) + else: + logger.fdebug("extra info given as :" + str(extra)) + logger.fdebug("extra information confirmed as a match") + logger.fdebug("queuing link: " + str(tor['Link'])) + tortheinfo.append({ + 'title': cttitle, #tor['Title'], + 'link': tor['Link'], + 'pubdate': tor['Pubdate'], + 'site': tor['Site'], + 'length': tor['Size'] + }) + logger.fdebug("entered info.") + continue + #torsend2client(formatrem_seriesname,tor['Link']) + else: + logger.fdebug("invalid issue#: " + str(sp)) + #extra = str(extra) + " " + str(sp) + else: + logger.fdebug("word detected - assuming continuation of title: " + str(sp)) + extra = str(extra) + " " + str(sp) + + torinfo['entries'] = tortheinfo + + return torinfo + +def nzbdbsearch(seriesname,issue,comicid=None): + myDB = db.DBConnection() + seriesname_alt = None + if comicid is None or comicid == 'None': + pass + else: + snm = myDB.action("SELECT * FROM comics WHERE comicid=?", [comicid]).fetchone() + if snm is None: + logger.info("Invalid ComicID of " + str(comicid) + ". Aborting search.") + return + else: + seriesname = snm['ComicName'] + seriesname_alt = snm['AlternateSearch'] + + + nsearch_seriesname = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.\s]', '%',seriesname) + formatrem_seriesname = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.]', '',seriesname) + nsearch = nsearch_seriesname + "%" + nresults = myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site != 'comicBT' AND Site != 'KAT'", [nsearch]) + if nresults is None: + logger.fdebug("nzb search returned no results for " + seriesname) + if seriesname_alt is None: + logger.fdebug("no nzb Alternate name given. Aborting search.") + return "no results" + else: + chkthealt = seriesname_alt.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + nresults += myDB.action("SELECT * FROM rssdb WHERE Title like ? AND Site != 'comicBT' AND Site != 'KAT'", [AS_Alternate]) + if nresults is None: + logger.fdebug("nzb alternate name search returned no results.") + return "no results" + + nzbtheinfo = [] + nzbinfo = {} + + for nzb in nresults: + # no need to parse here, just compile and throw it back .... + nzbtheinfo.append({ + 'title': nzb['Title'], + 'link': nzb['Link'], + 'pubdate': nzb['Pubdate'], + 'site': nzb['Site'], + 'length': nzb['Size'] + }) + logger.fdebug("entered info for " + nzb['Title']) + + nzbinfo['entries'] = nzbtheinfo + return nzbinfo + +def torsend2client(seriesname, linkit, site): + logger.info("matched on " + str(seriesname)) + filename = re.sub('[\'\!\@\#\$\%\:\;\/\\=\?\.]', '',seriesname) + if site == 'ComicBT': + logger.info(linkit) + linkit = str(linkit) + '&passkey=' + str(mylar.CBT_PASSKEY) + + if linkit[-7:] != "torrent": + filename += ".torrent" + + request = urllib2.Request(linkit) + request.add_header('User-Agent', str(mylar.USER_AGENT)) + if mylar.TORRENT_LOCAL and mylar.LOCAL_WATCHDIR is not None: + filepath = os.path.join(mylar.LOCAL_WATCHDIR, filename) + logger.fdebug("filename for torrent set to : " + filepath) + elif mylar.TORRENT_SEEDBOX and mylar.SEEDBOX_WATCHDIR is not None: + filepath = os.path.join(mylar.CACHE_DIR, filename) + logger.fdebug("filename for torrent set to : " + filepath) + else: + logger.error("No Local Watch Directory or Seedbox Watch Directory specified. Set it and try again.") + return "fail" + + try: + opener = helpers.urlretrieve(urllib2.urlopen(request), filepath) + except Exception, e: + logger.warn('Error fetching data from %s: %s' % (site, e)) + return "fail" + + logger.fdebug("torrent file saved as : " + str(filepath)) + if mylar.TORRENT_LOCAL: + return "pass" + #remote_file = urllib2.urlopen(linkit) + #if linkit[-7:] != "torrent": + # filename += ".torrent" + + #local_file = open('%s' % (os.path.join(mylar.CACHE_DIR,filename)), 'w') + #local_file.write(remote_file.read()) + #local_file.close() + #remote_file.close() + elif mylar.TORRENT_SEEDBOX: + tssh = ftpsshup.putfile(filepath,filename) + return tssh + +if __name__ == '__main__': + #torrents(sys.argv[1]) + #torrentdbsearch(sys.argv[1], sys.argv[2], sys.argv[3]) + nzbs(sys.argv[1]) diff --git a/mylar/search.py b/mylar/search.py index 78b67312..e6f4d731 100755 --- a/mylar/search.py +++ b/mylar/search.py @@ -1,3 +1,4 @@ + # This file is part of Mylar. # # Mylar is free software: you can redistribute it and/or modify @@ -16,7 +17,7 @@ from __future__ import division import mylar -from mylar import logger, db, updater, helpers, parseit, findcomicfeed, prov_nzbx, notifiers +from mylar import logger, db, updater, helpers, parseit, findcomicfeed, prov_nzbx, notifiers, rsscheck nzbsu_APIkey = mylar.NZBSU_APIKEY dognzb_APIkey = mylar.DOGNZB_APIKEY @@ -36,7 +37,7 @@ from xml.dom.minidom import parseString import urllib2 from datetime import datetime -def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, IssueDate, IssueID, AlternateSearch=None, UseFuzzy=None, ComicVersion=None, SARC=None, IssueArcID=None, mode=None): +def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, IssueDate, IssueID, AlternateSearch=None, UseFuzzy=None, ComicVersion=None, SARC=None, IssueArcID=None, mode=None, rsscheck=None): if ComicYear == None: ComicYear = '2013' else: ComicYear = str(ComicYear)[:4] @@ -57,6 +58,16 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, IssueDate, IssueI print ("Story-ARC issue!") print ("Story-ARC: " + str(SARC)) print ("IssueArcID: " + str(IssueArcID)) + + torprovider = [] + torp = 0 + logger.fdebug("Checking for torrent enabled.") + if mylar.ENABLE_TORRENTS and mylar.ENABLE_TORRENT_SEARCH: + if mylar.ENABLE_CBT: + torprovider.append('cbt') + torp+=1 + #print torprovider[0] + ##nzb provider selection## ##'dognzb' or 'nzb.su' or 'experimental' nzbprovider = [] @@ -83,22 +94,25 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, IssueDate, IssueI if mylar.NEWZNAB == 1: for newznab_host in mylar.EXTRA_NEWZNABS: - if newznab_host[2] == '1' or newznab_host[2] == 1: + if newznab_host[3] == '1' or newznab_host[3] == 1: newznab_hosts.append(newznab_host) - try: - if newznab_host[3] is None: - nzbprovider.append('newznab') - else: - nzbprovider.append(newznab_host[3]) - except: + if newznab_host[0] == newznab_host[1]: nzbprovider.append('newznab') - logger.error("newznab name not given for " + str(newznab_host[0]) + ". Defaulting name to newznab.") + else: + nzbprovider.append('newznab:' + str(newznab_host[0])) +# except: +# nzbprovider.append('newznab') +# logger.error("newznab name not given for " + str(newznab_host[0]) + ". Defaulting name to newznab.") newznabs+=1 - logger.fdebug("newznab host:" + str(newznab_host[0]) + " - enabled: " + str(newznab_host[2])) + logger.fdebug("newznab name:" + str(newznab_host[0]) + " @ " + str(newznab_host[1])) # -------- + logger.fdebug("there are : " + str(torp) + " torrent providers you have selected.") + torpr = torp - 1 + if torpr < 0: + torpr = -1 providercount = int(nzbp + newznabs) logger.fdebug("there are : " + str(providercount) + " search providers you have selected.") logger.fdebug("Usenet Retention : " + str(mylar.USENET_RETENTION) + " days") @@ -114,97 +128,159 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, IssueDate, IssueI else: IssDateFix = "no" - while (nzbpr >= 0 ): - if nzbprovider[nzbpr] == 'newznab': - #this is for newznab - nzbprov = 'newznab' - for newznab_host in newznab_hosts: - findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - logger.fdebug("findit = found!") - break - else: - if AlternateSearch is not None and AlternateSearch != "None": - logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AlternateSearch) + " " + str(ComicYear)) - findit = NZB_SEARCH(AlternateSearch, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + while (torpr >=0 ): + if torprovider[torpr] == 'cbt': + # ComicBT + torprov = 'ComicBT' + findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, torprov, torpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + if findit == 'yes': + logger.fdebug("findit = found!") + break + else: + if AlternateSearch is not None and AlternateSearch != "None": + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + loopit = len(chkthealt) + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate) + " " + str(ComicYear)) + findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, torprov, torp, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) if findit == 'yes': break - nzbpr-=1 - elif nzbprovider[nzbpr] == 'experimental': - #this is for experimental - nzbprov = 'experimental' - findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - logger.fdebug("findit = found!") - break + torpr-=1 + + if findit == 'yes': return findit, torprov + + searchcnt = 0 + nzbprov = None + if rsscheck: + searchcnt = 1 # rss-only + else: + searchcnt = 2 # rss first, then api on non-matches + + i = 1 + nzbsrchproviders = nzbpr + + while ( i <= searchcnt ): + #searchmodes: + # rss - will run through the built-cached db of entries + # api - will run through the providers via api (or non-api in the case of Experimental) + # the trick is if the search is done during an rss compare, it needs to exit when done. + # otherwise, the order of operations is rss feed check first, followed by api on non-results. + + if i == 1: searchmode = 'rss' #order of ops - this will be used first. + elif i == 2: searchmode = 'api' + + nzbpr = nzbsrchproviders + logger.fdebug("Initiating Search via : " + str(searchmode)) + + while (nzbpr >= 0 ): + if 'newznab' in nzbprovider[nzbpr]: + #this is for newznab + nzbprov = 'newznab' + for newznab_host in newznab_hosts: + #if it's rss - search both seriesname/alternates via rss then return. + if searchmode == 'rss': + if mylar.ENABLE_RSS: + findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes") + if findit == 'yes': + logger.fdebug("Found via RSS.") + break + #findit = altdefine(AlternateSearch, searchmode='rss') + if AlternateSearch is not None and AlternateSearch != "None": + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + loopit = len(chkthealt) + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate) + " " + str(ComicYear)) + findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes") + if findit == 'yes': + break + if findit == 'yes': + logger.fdebug("Found via RSS Alternate Naming.") + break + else: + logger.fdebug("RSS search not enabled - using API only (Enable in the Configuration)") + break + else: + #normal api-search here. + findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + if findit == 'yes': + logger.fdebug("Found via API.") + break + if AlternateSearch is not None and AlternateSearch != "None": + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + loopit = len(chkthealt) + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate) + " " + str(ComicYear)) + findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + if findit == 'yes': + break + if findit == 'yes': + logger.fdebug("Found via API Alternate Naming.") + break else: - if AlternateSearch is not None and AlternateSearch != "None": - logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AlternateSearch) + " " + str(ComicYear)) - findit = NZB_SEARCH(AlternateSearch, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': + nzbprov = nzbprovider[nzbpr] + if searchmode == 'rss': + if mylar.ENABLE_RSS: + findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS='yes') + if findit == 'yes': + logger.fdebug("Found via RSS on " + nzbprov) + break + if AlternateSearch is not None and AlternateSearch != "None": + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + loopit = len(chkthealt) + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate) + " " + str(ComicYear)) + findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes") + if findit == 'yes': + logger.fdebug("Found via RSS Alternate Naming on " + nzbprov) + break + else: + logger.fdebug("RSS search not enabled - using API only (Enable in the Configuration)") break - + else: + #normal api-search here. + findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + if findit == 'yes': + logger.fdebug("Found via API on " + nzbprov) + break + if AlternateSearch is not None and AlternateSearch != "None": + chkthealt = AlternateSearch.split('##') + if chkthealt == 0: + AS_Alternate = AlternateSearch + for calt in chkthealt: + AS_Alternate = re.sub('##','',calt) + logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate)) + findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion, SARC=SARC, IssueArcID=IssueArcID) + if findit == 'yes': + break + if findit == 'yes': + logger.fdebug("Found via API Alternate Naming on " + nzbprov) + break nzbpr-=1 - - elif nzbprovider[nzbpr] == 'nzbx': - # this is for nzbx.co - nzbprov = 'nzbx' - findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - logger.fdebug("findit = found!") - break + if nzbpr >= 0 and findit != 'yes': + logger.info(u"More than one search provider given - trying next one.") else: - if AlternateSearch is not None and AlternateSearch != "None": - logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AlternateSearch) + " " + str(ComicYear)) - findit = NZB_SEARCH(AlternateSearch, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - break - - nzbpr-=1 - - elif nzbprovider[nzbpr] == 'nzb.su': - # this is for nzb.su - nzbprov = 'nzb.su' - findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - logger.fdebug("findit = found!") break - else: - if AlternateSearch is not None and AlternateSearch != "None": - logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AlternateSearch) + " " + str(ComicYear)) - findit = NZB_SEARCH(AlternateSearch, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - break - - nzbpr-=1 - - # ---- - - elif nzbprovider[nzbpr] == 'dognzb': - # this is for dognzb.com - nzbprov = 'dognzb' - findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - - if findit == 'yes': - logger.fdebug("findit = found!") - break - else: - if AlternateSearch is not None and AlternateSearch != "None": - logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AlternateSearch) + " " + str(ComicYear)) - findit = NZB_SEARCH(AlternateSearch, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID) - if findit == 'yes': - break - - nzbpr-=1 - - if nzbpr >= 0 and findit != 'yes': - logger.info(u"More than one search provider given - trying next one.") - # ---- if findit == 'yes': return findit, nzbprov + else: + logger.fdebug("Finished searching via : " + str(searchmode)) + i+=1 + return findit, nzbprov -def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host=None, ComicVersion=None, SARC=None, IssueArcID=None): +def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, IssDateFix, IssueID, UseFuzzy, newznab_host=None, ComicVersion=None, SARC=None, IssueArcID=None, RSS=None): if nzbprov == 'nzb.su': apikey = mylar.NZBSU_APIKEY @@ -215,11 +291,17 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is elif nzbprov == 'experimental': apikey = 'none' elif nzbprov == 'newznab': - host_newznab = newznab_host[0].rstrip() - apikey = newznab_host[1].rstrip() - logger.fdebug("using Newznab host of : " + str(host_newznab)) + #updated to include Newznab Name now + name_newznab = newznab_host[0].rstrip() + host_newznab = newznab_host[1].rstrip() + apikey = newznab_host[2].rstrip() + logger.fdebug("using Newznab host of : " + str(name_newznab)) - logger.info(u"Shhh be very quiet...I'm looking for " + ComicName + " issue: " + str(IssueNumber) + " (" + str(ComicYear) + ") using " + str(nzbprov)) + if RSS == "yes": + tmpprov = str(nzbprov) + " [RSS]" + else: + tmpprov = nzbprov + logger.info(u"Shhh be very quiet...I'm looking for " + ComicName + " issue: " + str(IssueNumber) + " (" + str(ComicYear) + ") using " + str(tmpprov)) if mylar.PREFERRED_QUALITY == 0: filetype = "" @@ -309,11 +391,12 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is findcomiciss.append(iss) #print ("we need : " + str(findcomic[findcount]) + " issue: #" + str(findcomiciss[findcount])) + cm1 = re.sub("[\/]", " ", str(findcomic[findcount])) # replace whitespace in comic name with %20 for api search - cm1 = re.sub(" ", "%20", str(findcomic[findcount])) #cm = re.sub("\&", "%26", str(cm1)) - cm = re.sub("\\band\\b", "", str(cm1)) # remove 'and' & '&' from the search pattern entirely (broader results, will filter out later) + cm = re.sub("\\band\\b", "", cm1.lower()) # remove 'and' & '&' from the search pattern entirely (broader results, will filter out later) cm = re.sub("\\bthe\\b", "", cm.lower()) # remove 'the' from the search pattern to accomodate naming differences + cm = re.sub(" ", "%20", str(cm)) cm = re.sub("[\&\:\?\,]", "", str(cm)) #print (cmi) if '.' in findcomiciss[findcount]: @@ -356,77 +439,103 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is # here we account for issue pattern variations if cmloopit == 3: comsearch[findloop] = comsrc + "%2000" + isssearch[findloop] + "%20" + str(issue_exc) + "%20" + str(filetype) + issdig = '00' elif cmloopit == 2: comsearch[findloop] = comsrc + "%200" + isssearch[findloop] + "%20" + str(issue_exc) + "%20" + str(filetype) + issdig = '0' elif cmloopit == 1: comsearch[findloop] = comsrc + "%20" + isssearch[findloop] + "%20" + str(issue_exc) + "%20" + str(filetype) + issdig = '' #logger.fdebug("comsearch: " + str(comsearch)) #logger.fdebug("cmloopit: " + str(cmloopit)) #logger.fdebug("done: " + str(done)) - if nzbprov != 'experimental': - if nzbprov == 'dognzb': - findurl = "http://dognzb.cr/api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" - elif nzbprov == 'nzb.su': - findurl = "https://nzb.su/api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" - elif nzbprov == 'newznab': - #let's make sure the host has a '/' at the end, if not add it. - if host_newznab[len(host_newznab)-1:len(host_newznab)] != '/': - host_newznab_fix = str(host_newznab) + "/" - else: host_newznab_fix = host_newznab - findurl = str(host_newznab_fix) + "api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" - elif nzbprov == 'nzbx': - bb = prov_nzbx.searchit(comsearch[findloop]) - if nzbprov != 'nzbx': - # helper function to replace apikey here so we avoid logging it ;) - findurl = findurl + "&apikey=" + str(apikey) - logsearch = helpers.apiremove(str(findurl),'nzb') - logger.fdebug("search-url: " + str(logsearch)) + #--- this is basically for RSS Feeds --- + if RSS == "yes": + if nzbprov == 'ComicBT': + cmname = re.sub("%20", " ", str(comsrc)) + logger.fdebug("Sending request to [ComicBT] RSS for " + str(cmname) + " : " + str(issdig) + str(isssearch[findloop])) + bb = rsscheck.torrentdbsearch(cmname,isssearch[findloop]) + rss = "yes" + if bb is not None: logger.fdebug("bb results: " + str(bb)) + else: + cmname = re.sub("%20", " ", str(comsrc)) + logger.fdebug("Sending request to RSS for " + str(cmname) + " : " + str(issdig) + str(isssearch[findloop])) + bb = rsscheck.nzbdbsearch(cmname,isssearch[findloop]) + rss = "yes" + if bb is not None: logger.fdebug("bb results: " + str(bb)) + else: + #CBT is redudant now - just getting it ready for when it's not redudant :) + if nzbprov == 'ComicBT': + cmname = re.sub("%20", " ", str(comsrc)) + logger.fdebug("Sending request to [ComicBT] RSS for " + str(cmname) + " : " + str(issdig) + str(isssearch[findloop])) + bb = rsscheck.torrentdbsearch(cmname,isssearch[findloop]) + rss = "yes" + if bb is not None: logger.fdebug("results: " + str(bb)) - ### IF USENET_RETENTION is set, honour it - ### For newznab sites, that means appending "&maxage=" on the URL - if mylar.USENET_RETENTION != None: - findurl = findurl + "&maxage=" + str(mylar.USENET_RETENTION) + elif nzbprov != 'experimental': + if nzbprov == 'dognzb': + findurl = "http://dognzb.cr/api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" + elif nzbprov == 'nzb.su': + findurl = "https://nzb.su/api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" + elif nzbprov == 'newznab': + #let's make sure the host has a '/' at the end, if not add it. + if host_newznab[len(host_newznab)-1:len(host_newznab)] != '/': + host_newznab_fix = str(host_newznab) + "/" + else: host_newznab_fix = host_newznab + findurl = str(host_newznab_fix) + "api?t=search&q=" + str(comsearch[findloop]) + "&o=xml&cat=7030" + elif nzbprov == 'nzbx': + bb = prov_nzbx.searchit(comsearch[findloop]) + if nzbprov != 'nzbx': + # helper function to replace apikey here so we avoid logging it ;) + findurl = findurl + "&apikey=" + str(apikey) + logsearch = helpers.apiremove(str(findurl),'nzb') + logger.fdebug("search-url: " + str(logsearch)) - # Add a user-agent - #print ("user-agent:" + str(mylar.USER_AGENT)) - request = urllib2.Request(findurl) - request.add_header('User-Agent', str(mylar.USER_AGENT)) - opener = urllib2.build_opener() + ### IF USENET_RETENTION is set, honour it + ### For newznab sites, that means appending "&maxage=" on the URL + if mylar.USENET_RETENTION != None: + findurl = findurl + "&maxage=" + str(mylar.USENET_RETENTION) - #set a delay between searches here. Default is for 30 seconds... - if mylar.SEARCH_DELAY == 'None' or mylar.SEARCH_DELAY is None: - pause_the_search = 1 * 60 # (it's in seconds) - elif str(mylar.SEARCH_DELAY).isdigit(): - pause_the_search = mylar.SEARCH_DELAY * 60 - else: - logger.info("Check Search Delay - invalid numerical given. Force-setting to 1 minute.") - pause_the_search = 1 * 60 + # Add a user-agent + #print ("user-agent:" + str(mylar.USER_AGENT)) + request = urllib2.Request(findurl) + request.add_header('User-Agent', str(mylar.USER_AGENT)) + opener = urllib2.build_opener() - #bypass for local newznabs - if nzbprov == 'newznab': - if host_newznab_fix[:3] == '10.' or host_newznab_fix[:4] == '172.' or host_newznab_fix[:4] == '192.' or 'localhost' in str(host_newznab_fix): - pass + #set a delay between searches here. Default is for 30 seconds... + if mylar.SEARCH_DELAY == 'None' or mylar.SEARCH_DELAY is None: + pause_the_search = 1 * 60 # (it's in seconds) + elif str(mylar.SEARCH_DELAY).isdigit(): + pause_the_search = mylar.SEARCH_DELAY * 60 else: - logger.fdebug("pausing for " + str(pause_the_search) + " seconds before continuing to avoid hammering") - time.sleep(pause_the_search) + logger.info("Check Search Delay - invalid numerical given. Force-setting to 1 minute.") + pause_the_search = 1 * 60 - try: - data = opener.open(request).read() - except Exception, e: - logger.warn('Error fetching data from %s: %s' % (nzbprov, e)) - data = False + #bypass for local newznabs + if nzbprov == 'newznab': + if host_newznab_fix[:3] == '10.' or host_newznab_fix[:4] == '172.' or host_newznab_fix[:4] == '192.' or 'localhost' in str(host_newznab_fix): + pass + else: + logger.fdebug("pausing for " + str(pause_the_search) + " seconds before continuing to avoid hammering") + time.sleep(pause_the_search) - if data: - bb = feedparser.parse(data) - else: - bb = "no results" + try: + data = opener.open(request).read() + except Exception, e: + logger.warn('Error fetching data from %s: %s' % (nzbprov, e)) + data = False - elif nzbprov == 'experimental': - #bb = parseit.MysterBinScrape(comsearch[findloop], comyear) - bb = findcomicfeed.Startit(u_ComicName, isssearch[findloop], comyear, ComicVersion) - # since the regexs in findcomicfeed do the 3 loops, lets force the exit after - cmloopit == 1 + if data: + bb = feedparser.parse(data) + else: + bb = "no results" + + elif nzbprov == 'experimental': + #bb = parseit.MysterBinScrape(comsearch[findloop], comyear) + bb = findcomicfeed.Startit(u_ComicName, isssearch[findloop], comyear, ComicVersion) + # since the regexs in findcomicfeed do the 3 loops, lets force the exit after + cmloopit == 1 done = False foundc = "no" @@ -436,11 +545,18 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is foundc = "no" else: for entry in bb['entries']: - logger.fdebug("checking search result: " + str(entry['title'])) - if nzbprov != "experimental": - #Experimental already has size constraints done. - tmpsz = entry.enclosures[0] - comsize_b = tmpsz['length'] + logger.fdebug("checking search result: " + entry['title']) + if nzbprov != "experimental" and nzbprov != "ComicBT": + if RSS == "yes": + comsize_b = entry['length'] + else: + #Experimental already has size constraints done. + if nzbprov == 'ComicBT': + comsize_b = 0 #CBT rss doesn't have sizes + else: + tmpsz = entry.enclosures[0] + comsize_b = tmpsz['length'] + if comsize_b is None: comsize_b = 0 comsize_m = helpers.human_size(comsize_b) logger.fdebug("size given as: " + str(comsize_m)) #----size constraints. @@ -461,10 +577,10 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is # -- end size constaints. - thisentry = str(entry['title']) - logger.fdebug("Entry: " + str(thisentry)) - cleantitle = re.sub('[_/.]', ' ', str(entry['title'])) - cleantitle = helpers.cleanName(str(cleantitle)) + thisentry = entry['title'] + logger.fdebug("Entry: " + thisentry) + cleantitle = re.sub('[_/.]', ' ', entry['title']) + cleantitle = helpers.cleanName(cleantitle) # this is new - if title contains a '&' in the title it will assume the filename has ended at that point # which causes false positives (ie. wolverine & the x-men becomes the x-men, which matches on x-men. # 'the' is removed for comparisons later on @@ -472,6 +588,12 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is nzbname = cleantitle + # if it's coming from CBT, remove the ' -' at the end as it screws it up. + if nzbprov == 'ComicBT': + if cleantitle.endswith(' - '): + cleantitle = cleantitle[:-3] + logger.fdebug("cleaned up title to : " + str(cleantitle)) + # if there are no () in the string, try to add them if it looks like a year (19xx or 20xx) if len(re.findall('[^()]+', cleantitle)): @@ -481,10 +603,34 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is #adjust for covers only by removing them entirely... logger.fdebug("Cleantitle: " + str(cleantitle)) + vers4year = "no" + vers4vol = "no" if len(re.findall('[^()]+', cleantitle)) == 1 or 'cover only' in cleantitle.lower(): - logger.fdebug("invalid nzb and/or cover only - skipping.") - cleantitle = "abcdefghijk 0 (1901).cbz" - continue + #some sites don't have (2013) or whatever..just v2 / v2013. Let's adjust: + ctchk = cleantitle.split() + for ct in ctchk: + if 'v' in ct.lower() and ct[1:].isdigit(): + logger.fdebug("possible versioning..checking") + #we hit a versioning # - account for it + if ct[1:].isdigit(): + if len(ct[1:]) == 4: #v2013 + logger.fdebug("Version detected as " + str(ct)) + vers4year = "yes" #re.sub("[^0-9]", " ", str(ct)) #remove the v + #cleantitle = re.sub(ct, "(" + str(vers4year) + ")", cleantitle) + #logger.fdebug("volumized cleantitle : " + cleantitle) + break + elif len(ct[1:]) == 1: #v2 + logger.fdebug("Version detected as " + str(ct)) + vers4vol = str(ct) + break + else: + logger.fdebug("error - unknown length for : " + str(ct)) + cleantitle = "abcdefghijk 0 (1901).cbz" + break + if vers4year == "no" and vers4vol == "no": + logger.fdebug("invalid nzb and/or cover only - skipping.") + cleantitle = "abcdefghijk 0 (1901).cbz" + continue if done: break @@ -513,7 +659,10 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is comic_andiss = m[cnt] logger.fdebug("Comic: " + str(comic_andiss)) logger.fdebug("UseFuzzy is : " + str(UseFuzzy)) - if UseFuzzy == "0" or UseFuzzy == "2" or UseFuzzy is None or IssDateFix != "no": + if vers4vol != "no" or vers4year != "no": + logger.fdebug("Year not given properly formatted but Version detected.Bypassing Year Match.") + yearmatch = "true" + elif UseFuzzy == "0" or UseFuzzy == "2" or UseFuzzy is None or IssDateFix != "no": if m[cnt][:-2] == '19' or m[cnt][:-2] == '20': logger.fdebug("year detected: " + str(m[cnt])) result_comyear = m[cnt] @@ -590,8 +739,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is findcomic_chksplit = re.sub('[\-\:\,\.\?]', ' ', findcomic[findloop]) chg_comic = re.sub('[\s]', '', chg_comic) findcomic_chksplit = re.sub('[\s]', '', findcomic_chksplit) - print chg_comic.upper() - print findcomic_chksplit.upper() + #print chg_comic.upper() + #print findcomic_chksplit.upper() if chg_comic.upper() == findcomic_chksplit.upper(): logger.fdebug("series contains numerics...adjusting..") else: @@ -609,6 +758,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is #else: splitst = len(splitit) - 1 # make sure that things like - in watchcomic are accounted for when comparing to nzb. + findcomic[findloop] = re.sub('[\/]', ' ', findcomic[findloop]) watchcomic_split = helpers.cleanName(str(findcomic[findloop])) if '&' in watchcomic_split: watchcomic_split = re.sub('[/&]','and', watchcomic_split) watchcomic_nonsplit = re.sub('[\-\:\,\.\?]', ' ', watchcomic_split) @@ -632,20 +782,29 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is initialchk = 'ok' if (splitst) != len(watchcomic_split): logger.fdebug("incorrect comic lengths...not a match") - if str(splitit[0]).lower() == "the" or str(watchcomic_split[0]).lower() == "the": - if str(splitit[0]).lower() == "the": - logger.fdebug("THE word detected...attempting to adjust pattern matching") - #print comic_iss - #print comic_iss[4:] - splitit = comic_iss_b4[4:].split(None) - #splitit = splitit[4:] + #because the word 'the' can appear anywhere and really mess up matches... +# if str(splitit[0]).lower() == "the" or str(watchcomic_split[0]).lower() == "the": +# if str(splitit[0]).lower() == "the": + for tstsplit in splitit: + if tstsplit.lower == 'the': + logger.fdebug("THE word detected in found comic...attempting to adjust pattern matching") + #print comic_iss_b4 + #print comic_iss_b4[4:] + #splitit = comic_iss_b4[4:].split(None) + cissb4this = re.sub("\\bthe\\b", "", comic_iss_b4) + splitit = cissb4this.split(None) splitst = splitst - 1 #remove 'the' from start - logger.fdebug("comic is now : " + str(comic_iss_b4[4:])) - if str(watchcomic_split[0]).lower() == "the": - wtstart = watchcomic_nonsplit[4:] + logger.fdebug("comic is now : " + str(splitit))#str(comic_iss[4:])) + #if str(watchcomic_split[0]).lower() == "the": + for tstsplit in watchcomic_split: + if tstsplit.lower() == 'the': + logger.fdebug("THE word detected in watchcomic - attempting to adjust match.") + #wtstart = watchcomic_nonsplit[4:] + #watchcomic_split = wtstart.split(None) + wtstart = re.sub("\\bthe\\b", "", watchcomic_nonsplit) watchcomic_split = wtstart.split(None) logger.fdebug("new watchcomic string:" + str(watchcomic_split)) - initialchk = 'no' + initialchk = 'no' else: initialchk = 'ok' @@ -660,6 +819,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is if cvers == "true": splitst = splitst + 1 while ( n <= (splitst)-1 ): logger.fdebug("splitit: " + str(splitit[n])) + logger.fdebug("scount : " + str(scount)) if n < (splitst) and n < len(watchcomic_split): logger.fdebug(str(n) + " Comparing: " + str(watchcomic_split[n]) + " .to. " + str(splitit[n])) if '+' in watchcomic_split[n]: @@ -677,11 +837,17 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is logger.fdebug("watch comicversion is " + str(ComicVersion)) fndcomicversion = str(splitit[n]) logger.fdebug("version found: " + str(fndcomicversion)) - if ComicVersion != "None" and ComicVersion is not None: + if vers4year != "no" or vers4vol != "no": + if ComicVersion != "None" and ComicVersion is not None: + D_ComicVersion = re.sub("[^0-9]", "", ComicVersion) + else: + D_ComicVersion = 0 + F_ComicVersion = re.sub("[^0-9]", "", fndcomicversion) - D_ComicVersion = re.sub("[^0-9]", "", ComicVersion) - if int(F_ComicVersion) == int(D_ComicVersion): - logger.fdebug("We matched on versions...") + S_ComicVersion = str(SeriesYear) + + if int(F_ComicVersion) == int(D_ComicVersion) or int(F_ComicVersion) == int(S_ComicVersion): + logger.fdebug("We matched on versions..." + str(fndcomicversion)) scount+=1 else: logger.fdebug("Versions wrong. Ignoring possible match.") @@ -757,7 +923,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is #issue comparison now as well if int(intIss) == int(comintIss): logger.fdebug('issues match!') - logger.info(u"Found " + ComicName + " (" + str(comyear) + ") issue: " + str(IssueNumber) + " using " + str(nzbprov) ) + logger.info(u"Found " + ComicName + " (" + str(comyear) + ") issue: " + str(IssueNumber) + " using " + str(tmpprov) ) ## -- inherit issue. Comic year is non-standard. nzb year is the year ## -- comic was printed, not the start year of the comic series and ## -- thus the deciding component if matches are correct or not @@ -789,7 +955,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is request = urllib2.Request(linkapi) #(str(mylar.BLACKHOLE_DIR) + str(filenamenzb)) request.add_header('User-Agent', str(mylar.USER_AGENT)) try: - opener = urlretrieve(urllib2.urlopen(request), str(mylar.BLACKHOLE_DIR) + str(filenamenzb)) + opener = helpers.urlretrieve(urllib2.urlopen(request), str(mylar.BLACKHOLE_DIR) + str(filenamenzb)) except Exception, e: logger.warn('Error fetching data from %s: %s' % (nzbprov, e)) return @@ -803,7 +969,24 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is nzbname = re.sub(str(ext), '', str(filenamenzb)) logger.fdebug("nzb name to be used for post-processing is : " + str(nzbname)) #end blackhole + elif nzbprov == 'ComicBT': + logger.fdebug("sending .torrent to watchdir.") + logger.fdebug("ComicName:" + ComicName) + logger.fdebug("link:" + entry['link']) + logger.fdebug("Torrent Provider:" + nzbprov) + foundc = "yes" + #let's change all space to decimals for simplicity + nzbname = re.sub(" ", ".", str(entry['title'])) + #gotta replace & or escape it + nzbname = re.sub("\&", 'and', str(nzbname)) + nzbname = re.sub('[\,\:\?]', '', str(nzbname)) + if nzbname.lower().endswith('.torrent'): + nzbname = re.sub('.torrent', '', nzbname) + rcheck = rsscheck.torsend2client(ComicName, entry['link'], nzbprov) + if rcheck == "fail": + logger.error("Unable to send torrent - check logs and settings.") + return else: tmppath = mylar.CACHE_DIR if os.path.exists(tmppath): @@ -899,18 +1082,18 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is logger.info(u"Successfully sent nzb file to SABnzbd") - if mylar.PROWL_ENABLED and mylar.PROWL_ONSNATCH: - logger.info(u"Sending Prowl notification") - prowl = notifiers.PROWL() - prowl.notify(nzbname,"Download started") - if mylar.NMA_ENABLED and mylar.NMA_ONSNATCH: - logger.info(u"Sending NMA notification") - nma = notifiers.NMA() - nma.notify(snatched_nzb=nzbname) - if mylar.PUSHOVER_ENABLED and mylar.PUSHOVER_ONSNATCH: - logger.info(u"Sending Pushover notification") - pushover = notifiers.PUSHOVER() - pushover.notify(nzbname,"Download started") + if mylar.PROWL_ENABLED and mylar.PROWL_ONSNATCH: + logger.info(u"Sending Prowl notification") + prowl = notifiers.PROWL() + prowl.notify(nzbname,"Download started") + if mylar.NMA_ENABLED and mylar.NMA_ONSNATCH: + logger.info(u"Sending NMA notification") + nma = notifiers.NMA() + nma.notify(snatched_nzb=nzbname) + if mylar.PUSHOVER_ENABLED and mylar.PUSHOVER_ONSNATCH: + logger.info(u"Sending Pushover notification") + pushover = notifiers.PUSHOVER() + pushover.notify(nzbname,"Download started") foundc = "yes" done = True @@ -932,25 +1115,49 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is return foundc elif foundc == "no" and nzbpr == 0: foundcomic.append("no") - logger.fdebug("couldn't find a matching comic") + logger.fdebug("couldn't find a matching comic using " + str(tmpprov)) if IssDateFix == "no": logger.info(u"Couldn't find Issue " + str(IssueNumber) + " of " + ComicName + "(" + str(comyear) + "). Status kept as wanted." ) break return foundc -def searchforissue(issueid=None, new=False): +def searchforissue(issueid=None, new=False, rsscheck=None): myDB = db.DBConnection() - if not issueid: + if not issueid or rsscheck: - logger.info(u"Initiating NZB Search scan at requested interval of " + str(mylar.SEARCH_INTERVAL) + " minutes.") + if rsscheck: + logger.info(u"Initiating RSS Search Scan at scheduled interval of " + str(mylar.RSS_CHECKINTERVAL) + " minutes.") + else: + logger.info(u"Initiating NZB Search scan at requested interval of " + str(mylar.SEARCH_INTERVAL) + " minutes.") myDB = db.DBConnection() - results = myDB.select('SELECT * from issues WHERE Status="Wanted"') + stloop = 1 + results = [] - # annuals include here... - #results += myDB.select('SELECT * from annuals WHERE Status="Wanted"') + if mylar.ANNUALS_ON: + stloop+=1 + while (stloop > 0): + if stloop == 1: + issues_1 = myDB.select('SELECT * from issues WHERE Status="Wanted"') + for iss in issues_1: + results.append({'ComicID': iss['ComicID'], + 'IssueID': iss['IssueID'], + 'Issue_Number': iss['Issue_Number'], + 'IssueDate': iss['IssueDate'], + 'mode': 'want' + }) + elif stloop == 2: + issues_2 = myDB.select('SELECT * from annuals WHERE Status="Wanted"') + for iss in issues_2: + results.append({'ComicID': iss['ComicID'], + 'IssueID': iss['IssueID'], + 'Issue_Number': iss['Issue_Number'], + 'IssueDate': iss['IssueDate'], + 'mode': 'want_ann' + }) + stloop-=1 new = True @@ -963,15 +1170,15 @@ def searchforissue(issueid=None, new=False): UseFuzzy = comic['UseFuzzy'] ComicVersion = comic['ComicVersion'] if result['IssueDate'] == None: - IssueYear = comic['ComicYear'] + ComicYear = comic['ComicYear'] else: - IssueYear = str(result['IssueDate'])[:4] - - if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.NZBX) and (mylar.USE_SABNZBD or mylar.USE_NZBGET): - foundNZB = search_init(result['ComicName'], result['Issue_Number'], str(IssueYear), comic['ComicYear'], IssueDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode) + ComicYear = str(result['IssueDate'])[:4] + mode = result['mode'] + if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.NZBX or mylar.ENABLE_KAT or mylar.ENABLE_CBT) and (mylar.USE_SABNZBD or mylar.USE_NZBGET or mylar.ENABLE_TORRENTS): + foundNZB, prov = search_init(comic['ComicName'], result['Issue_Number'], str(ComicYear), comic['ComicYear'], IssueDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, rsscheck=rsscheck) if foundNZB == "yes": #print ("found!") - updater.foundsearch(result['ComicID'], result['IssueID'], mode=mode) + updater.foundsearch(result['ComicID'], result['IssueID'], mode=mode, provider=prov) else: pass #print ("not found!") @@ -981,6 +1188,9 @@ def searchforissue(issueid=None, new=False): if result is None: result = myDB.action('SELECT * FROM annuals where IssueID=?', [issueid]).fetchone() mode = 'want_ann' + if result is None: + logger.info("Unable to locate IssueID - you probably should delete/refresh the series.") + return ComicID = result['ComicID'] comic = myDB.action('SELECT * FROM comics where ComicID=?', [ComicID]).fetchone() SeriesYear = comic['ComicYear'] @@ -995,10 +1205,10 @@ def searchforissue(issueid=None, new=False): foundNZB = "none" if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.NZBX) and (mylar.USE_SABNZBD or mylar.USE_NZBGET): - foundNZB = search_init(result['ComicName'], result['Issue_Number'], str(IssueYear), comic['ComicYear'], IssueDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, mode=mode) + foundNZB, prov = search_init(result['ComicName'], result['Issue_Number'], str(IssueYear), comic['ComicYear'], IssueDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, mode=mode) if foundNZB == "yes": logger.fdebug("I found " + result['ComicName'] + ' #:' + str(result['Issue_Number'])) - updater.foundsearch(ComicID=result['ComicID'], IssueID=result['IssueID'], mode=mode) + updater.foundsearch(ComicID=result['ComicID'], IssueID=result['IssueID'], mode=mode, provider=prov) else: pass #print ("not found!") @@ -1012,6 +1222,9 @@ def searchIssueIDList(issuelist): if issue is None: issue = myDB.action('SELECT * from annuals WHERE IssueID=?', [issueid]).fetchone() mode = 'want_ann' + if issue is None: + logger.info("unable to determine IssueID - perhaps you need to delete/refresh series?") + break comic = myDB.action('SELECT * from comics WHERE ComicID=?', [issue['ComicID']]).fetchone() print ("Checking for issue: " + str(issue['Issue_Number'])) foundNZB = "none" @@ -1023,22 +1236,12 @@ def searchIssueIDList(issuelist): IssueYear = comic['ComicYear'] else: IssueYear = str(issue['IssueDate'])[:4] - if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.NZBX) and (mylar.USE_SABNZBD or mylar.USE_NZBGET): - foundNZB = search_init(comic['ComicName'], issue['Issue_Number'], str(IssueYear), comic['ComicYear'], issue['IssueDate'], issue['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, mode=mode) + if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.NZBX or mylar.ENABLE_CBT or mylar.ENABLE_KAT) and (mylar.USE_SABNZBD or mylar.USE_NZBGET or mylar.ENABLE_TORRENTS): + foundNZB, prov = search_init(comic['ComicName'], issue['Issue_Number'], str(IssueYear), comic['ComicYear'], issue['IssueDate'], issue['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode) if foundNZB == "yes": #print ("found!") - updater.foundsearch(ComicID=issue['ComicID'], IssueID=issue['IssueID'], mode=mode) + updater.foundsearch(ComicID=issue['ComicID'], IssueID=issue['IssueID'], mode=mode, provider=prov) else: pass #print ("not found!") -def urlretrieve(urlfile, fpath): - chunk = 4096 - f = open(fpath, "w") - while 1: - data = urlfile.read(chunk) - if not data: - print "done." - break - f.write(data) - print "Read %s bytes"%len(data) diff --git a/mylar/updater.py b/mylar/updater.py index 862743ce..4709c58a 100755 --- a/mylar/updater.py +++ b/mylar/updater.py @@ -27,7 +27,7 @@ from mylar import db, logger, helpers, filechecker def dbUpdate(ComicIDList=None): myDB = db.DBConnection() - print "comicidlist:" + str(ComicIDList) + #print "comicidlist:" + str(ComicIDList) if ComicIDList is None: comiclist = myDB.select('SELECT ComicID, ComicName from comics WHERE Status="Active" or Status="Loading" order by LastUpdated ASC') else: @@ -37,7 +37,6 @@ def dbUpdate(ComicIDList=None): logger.info('Starting update for %i active comics' % len(comiclist)) for comic in comiclist: - print "comic" + comic if ComicIDList is None: comicid = comic[0] else: @@ -61,21 +60,37 @@ def dbUpdate(ComicIDList=None): #in order to update to JUST CV_ONLY, we need to delete the issues for a given series so it's a clean refresh. logger.fdebug("Gathering the status of all issues for the series.") issues = myDB.select('SELECT * FROM issues WHERE ComicID=?', [comicid]) + if mylar.ANNUALS_ON: + issues += myDB.select('SELECT * FROM annuals WHERE ComicID=?', [comicid]) #store the issues' status for a given comicid, after deleting and readding, flip the status back to what it is currently. logger.fdebug("Deleting all issue data.") myDB.select('DELETE FROM issues WHERE ComicID=?', [comicid]) + myDB.select('DELETE FROM annuals WHERE ComicID=?', [comicid]) logger.fdebug("Refreshing the series and pulling in new data using only CV.") mylar.importer.addComictoDB(comicid,mismatch) issues_new = myDB.select('SELECT * FROM issues WHERE ComicID=?', [comicid]) + annuals = [] + ann_list = [] + if mylar.ANNUALS_ON: + annuals_list = myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID]) + ann_list += annuals_list + issues_new += annuals_list + icount = 0 logger.fdebug("Attempting to put the Status' back how they were.") for issue in issues: for issuenew in issues_new: - if issuenew['IssueID'] == issue['IssueID'] and issuenew['Status'] != issue['Status']: + if issuenew['IssueID'] == issue['IssueID'] and issuenew['Status'] != issue['Status']: + #if the status is now Downloaded, keep status. + if issuenew['Status'] == 'Downloaded': break #change the status to the previous status ctrlVAL = {'IssueID': issue['IssueID']} newVAL = {'Status': issue['Status']} - myDB.upsert("Issues", newVAL, ctrlVAL) + if any(d['IssueID'] == str(issue['IssueID']) for d in ann_list): + logger.fdebug("annual detected for " + str(issue['IssueID']) + " #: " + str(issue['Issue_Number'])) + myDB.upsert("Annuals", newVAL, ctrlVAL) + else: + myDB.upsert("Issues", newVAL, ctrlVAL) icount+=1 break logger.info("In converting data to CV only, I changed the status of " + str(icount) + " issues.") @@ -97,10 +112,16 @@ def latest_update(ComicID, LatestIssue, LatestDate): def upcoming_update(ComicID, ComicName, IssueNumber, IssueDate, forcecheck=None): # here we add to upcoming table... myDB = db.DBConnection() - + dspComicName = ComicName #to make sure that the word 'annual' will be displayed on screen + if 'annual' in ComicName.lower(): + adjComicName = re.sub("\\bannual\\b", "", ComicName.lower()) # for use with comparisons. + logger.fdebug("annual detected - adjusting name to : " + adjComicName) + else: + adjComicName = ComicName controlValue = {"ComicID": ComicID} - newValue = {"ComicName": str(ComicName), + newValue = {"ComicName": adjComicName, "IssueNumber": str(IssueNumber), + "DisplayComicName": dspComicName, "IssueDate": str(IssueDate)} #let's refresh the artist here just to make sure if an issue is available/not. @@ -125,10 +146,14 @@ def upcoming_update(ComicID, ComicName, IssueNumber, IssueDate, forcecheck=None) # no need to hammer the refresh # let's check it every 5 hours (or more) #pullupd = "yes" + if 'annual' in ComicName.lower(): + if mylar.ANNUALS_ON: + issuechk = myDB.action("SELECT * FROM annuals WHERE ComicID=? AND Issue_Number=?", [ComicID, IssueNumber]).fetchone() + else: + issuechk = myDB.action("SELECT * FROM issues WHERE ComicID=? AND Issue_Number=?", [ComicID, IssueNumber]).fetchone() - issuechk = myDB.action("SELECT * FROM issues WHERE ComicID=? AND Issue_Number=?", [ComicID, IssueNumber]).fetchone() if issuechk is None: - logger.fdebug(ComicName + " Issue: " + str(IssueNumber) + " not present in listings to mark for download...updating comic and adding to Upcoming Wanted Releases.") + logger.fdebug(adjComicName + " Issue: " + str(IssueNumber) + " not present in listings to mark for download...updating comic and adding to Upcoming Wanted Releases.") # we need to either decrease the total issue count, OR indicate that an issue is upcoming. upco_results = myDB.action("SELECT COUNT(*) FROM UPCOMING WHERE ComicID=?",[ComicID]).fetchall() upco_iss = upco_results[0][0] @@ -154,7 +179,7 @@ def upcoming_update(ComicID, ComicName, IssueNumber, IssueDate, forcecheck=None) return elif issuechk['Issue_Number'] == IssueNumber: logger.fdebug("Comic series already up-to-date ... no need to refresh at this time.") - logger.fdebug("Available to be marked for download - checking..." + str(issuechk['ComicName']) + " Issue: " + str(issuechk['Issue_Number'])) + logger.fdebug("Available to be marked for download - checking..." + adjComicName + " Issue: " + str(issuechk['Issue_Number'])) logger.fdebug("...Existing status: " + str(issuechk['Status'])) control = {"IssueID": issuechk['IssueID']} newValue['IssueID'] = issuechk['IssueID'] @@ -206,7 +231,10 @@ def upcoming_update(ComicID, ComicName, IssueNumber, IssueDate, forcecheck=None) values = {"IssueDate": newValue['IssueDate']} #if ComicID[:1] == "G": mylar.importer.GCDimport(ComicID,pullupd='yes') #else: mylar.importer.addComictoDB(ComicID,mismatch,pullupd='yes') - myDB.upsert("issues", values, control) + if 'annual' in ComicName.lower(): + myDB.upsert("annuals", values, control) + else: + myDB.upsert("issues", values, control) if issuechk['Status'] == 'Downloaded': logger.fdebug("updating Pull-list to reflect status.") downstats = {"Status": issuechk['Status'], @@ -296,6 +324,7 @@ def foundsearch(ComicID, IssueID, mode=None, down=None, provider=None): if down is None: # update the status to Snatched (so it won't keep on re-downloading!) logger.fdebug("updating status to snatched") + logger.fdebug("provider is " + provider) controlValue = {"IssueID": IssueID} newValue = {"Status": "Snatched"} if mode == 'want_ann': @@ -305,9 +334,9 @@ def foundsearch(ComicID, IssueID, mode=None, down=None, provider=None): # update the snatched DB snatchedupdate = {"IssueID": IssueID, - "Status": "Snatched"}#, -# "Provider": Provider -# } + "Status": "Snatched", + "Provider": provider + } if mode == 'want_ann': IssueNum = "Annual " + issue['Issue_Number'] else: @@ -327,9 +356,9 @@ def foundsearch(ComicID, IssueID, mode=None, down=None, provider=None): IssueNum = issue['Issue_Number'] snatchedupdate = {"IssueID": IssueID, - "Status": "Downloaded"}#, -# "Provider": Provider -# } + "Status": "Downloaded", + "Provider": provider + } newsnatchValues = {"ComicName": comic['ComicName'], "ComicID": ComicID, "Issue_Number": IssueNum, @@ -383,7 +412,7 @@ def forceRescan(ComicID,archive=None): extensions = ('.cbr','.cbz') if temploc.lower().endswith(extensions): logger.fdebug("removed extension for issue:" + str(temploc)) - #temploc = temploc[:-4] + temploc = temploc[:-4] deccnt = str(temploc).count('.') if deccnt > 0: #logger.fdebug("decimal counts are :" + str(deccnt)) @@ -422,7 +451,10 @@ def forceRescan(ComicID,archive=None): #logger.fdebug("final filename to use is : " + str(tempreconstruct)) temploc = tempreconstruct #logger.fdebug("checking " + str(temploc)) - fcnew = shlex.split(str(temploc)) + #fcnew_b4 = shlex.split(str(temploc)) + fcnew_af = re.findall('[^\()]+', temploc) + fcnew = shlex.split(fcnew_af[0]) + fcn = len(fcnew) n = 0 while (n <= iscnt): @@ -483,10 +515,14 @@ def forceRescan(ComicID,archive=None): fcnew[som+1] = '93939999919190933' logger.info("AI Detected seperate from issue - combining and continuing") - fcdigit = helpers.issuedigits(fcnew[som]) + #sometimes scanners refuse to use spaces between () and lump the issue right at the start + #mylar assumes it's all one word in this case..let's dump the brackets. + fcredone = re.findall('[^\()]+', fcnew[som]) + + fcdigit = helpers.issuedigits(fcredone[0]) - #logger.fdebug("fcdigit: " + str(fcdigit)) - #logger.fdebug("int_iss: " + str(int_iss)) + logger.fdebug("fcdigit: " + str(fcdigit)) + logger.fdebug("int_iss: " + str(int_iss)) if int(fcdigit) == int_iss: logger.fdebug("issue match - fcdigit: " + str(fcdigit) + " ... int_iss: " + str(int_iss)) @@ -588,12 +624,13 @@ def forceRescan(ComicID,archive=None): if issuedupe == "yes": pass else: - logger.fdebug("issueID to write to db:" + str(reiss['IssueID'])) #we have the # of comics, now let's update the db. #even if we couldn't find the physical issue, check the status. if 'annual' in temploc.lower(): + logger.fdebug("issueID to write to db:" + str(reann['IssueID'])) controlValueDict = {"IssueID": str(reann['IssueID'])} else: + logger.fdebug("issueID to write to db:" + str(reiss['IssueID'])) controlValueDict = {"IssueID": reiss['IssueID']} #if Archived, increase the 'Have' count. @@ -614,6 +651,8 @@ def forceRescan(ComicID,archive=None): havefiles+=1 elif old_status == "Wanted": issStatus = "Wanted" + elif old_status == "Ignored": + issStatus = "Ignored" else: issStatus = "Skipped" @@ -643,6 +682,13 @@ def forceRescan(ComicID,archive=None): havefiles = havefiles + arcfiles logger.fdebug("Adjusting have total to " + str(havefiles) + " because of this many archive files:" + str(arcfiles)) + ignorecount = 0 + if mylar.IGNORE_HAVETOTAL: # if this is enabled, will increase Have total as if in Archived Status + ignores = myDB.action("SELECT count(*) FROM issues WHERE ComicID=? AND Status='Ignored'", [ComicID]).fetchall() + if int(ignores[0][0]) > 0: + ignorecount = ignores[0][0] + havefiles = havefiles + ignorecount + logger.fdebug("Adjusting have total to " + str(havefiles) + " because of this many Ignored files:" + str(ignorecount)) #now that we are finished... #adjust for issues that have been marked as Downloaded, but aren't found/don't exist. @@ -688,6 +734,6 @@ def forceRescan(ComicID,archive=None): } myDB.upsert("comics", newValueStat, controlValueStat) - logger.info(u"I've physically found " + str(foundcount) + " issues, and accounted for " + str(totalarc) + " in an Archived state. Total Issue Count: " + str(havefiles) + " / " + str(rescan['Total'])) + logger.info(u"I've physically found " + str(foundcount) + " issues, ignored " + str(ignorecount) + " issues, and accounted for " + str(totalarc) + " in an Archived state. Total Issue Count: " + str(havefiles) + " / " + str(rescan['Total'])) return diff --git a/mylar/webserve.py b/mylar/webserve.py index 2ef0a694..4d4f7d35 100755 --- a/mylar/webserve.py +++ b/mylar/webserve.py @@ -109,10 +109,11 @@ class WebInterface(object): isCounts[2] = 0 #2 wanted isCounts[3] = 0 #3 archived isCounts[4] = 0 #4 downloaded - isCounts[5] = 0 #5 read + isCounts[5] = 0 #5 ignored + #isCounts[6] = 0 #6 read for curResult in issues: - baseissues = {'skipped':1,'wanted':2,'archived':3,'downloaded':4} + baseissues = {'skipped':1,'wanted':2,'archived':3,'downloaded':4,'ignored':5} for seas in baseissues: if seas in curResult['Status'].lower(): sconv = baseissues[seas] @@ -122,7 +123,8 @@ class WebInterface(object): "Skipped" : str(isCounts[1]), "Wanted" : str(isCounts[2]), "Archived" : str(isCounts[3]), - "Downloaded" : str(isCounts[4]) + "Downloaded" : str(isCounts[4]), + "Ignored" : str(isCounts[5]) } usethefuzzy = comic['UseFuzzy'] skipped2wanted = "0" @@ -137,7 +139,6 @@ class WebInterface(object): if mylar.ANNUALS_ON: annuals = myDB.select("SELECT * FROM annuals WHERE ComicID=?", [ComicID]) else: annuals = None - print "blah" return serve_template(templatename="comicdetails.html", title=comic['ComicName'], comic=comic, issues=issues, comicConfig=comicConfig, isCounts=isCounts, series=series, annuals=annuals) comicDetails.exposed = True @@ -424,21 +425,37 @@ class WebInterface(object): #in order to update to JUST CV_ONLY, we need to delete the issues for a given series so it's a clea$ logger.fdebug("Gathering the status of all issues for the series.") issues = myDB.select('SELECT * FROM issues WHERE ComicID=?', [ComicID]) + if mylar.ANNUALS_ON: + issues += myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID]) #store the issues' status for a given comicid, after deleting and readding, flip the status back to$ logger.fdebug("Deleting all issue data.") myDB.select('DELETE FROM issues WHERE ComicID=?', [ComicID]) + myDB.select('DELETE FROM annuals WHERE ComicID=?', [ComicID]) logger.fdebug("Refreshing the series and pulling in new data using only CV.") mylar.importer.addComictoDB(ComicID,mismatch) - issues_new = myDB.select('SELECT * FROM issues WHERE ComicID=?', [ComicID]) + issues_new = myDB.select('SELECT * FROM issues WHERE ComicID=?', [ComicID]) + annuals = [] + ann_list = [] + if mylar.ANNUALS_ON: + annuals_list = myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID]) + ann_list += annuals_list + issues_new += annuals_list + logger.fdebug("Attempting to put the Status' back how they were.") icount = 0 for issue in issues: for issuenew in issues_new: if issuenew['IssueID'] == issue['IssueID'] and issuenew['Status'] != issue['Status']: + #if the status is now Downloaded, keep status. + if issuenew['Status'] == 'Downloaded': break #change the status to the previous status ctrlVAL = {'IssueID': issue['IssueID']} newVAL = {'Status': issue['Status']} - myDB.upsert("Issues", newVAL, ctrlVAL) + if any(d['IssueID'] == str(issue['IssueID']) for d in ann_list): + logger.fdebug("annual detected for " + str(issue['IssueID']) + " #: " + str(issue['Issue_Number'])) + myDB.upsert("Annuals", newVAL, ctrlVAL) + else: + myDB.upsert("Issues", newVAL, ctrlVAL) icount+=1 break logger.info("In the process of converting the data to CV, I changed the status of " + str(icount) + " issues.") @@ -480,6 +497,11 @@ class WebInterface(object): continue else: mi = myDB.action("SELECT * FROM issues WHERE IssueID=?",[IssueID]).fetchone() + annchk = 'no' + if mi is None: + if mylar.ANNUALS_ON: + mi = myDB.action("SELECT * FROM annuals WHERE IssueID=?",[IssueID]).fetchone() + annchk = 'yes' miyr = myDB.action("SELECT ComicYear FROM comics WHERE ComicID=?", [mi['ComicID']]).fetchone() if action == 'Downloaded': if mi['Status'] == "Skipped" or mi['Status'] == "Wanted": @@ -499,8 +521,11 @@ class WebInterface(object): myDB.action("DELETE FROM snatched WHERE IssueID=?", [IssueID]) controlValueDict = {"IssueID": IssueID} newValueDict = {"Status": newaction} - myDB.upsert("issues", newValueDict, controlValueDict) - print "updated...to " + str(newaction) + if annchk == 'yes': + myDB.upsert("annuals", newValueDict, controlValueDict) + else: + myDB.upsert("issues", newValueDict, controlValueDict) + logger.fdebug("updated...to " + str(newaction)) if len(issuestoArchive) > 0: updater.forceRescan(mi['ComicID']) if len(issuesToAdd) > 0: @@ -610,20 +635,36 @@ class WebInterface(object): def unqueueissue(self, IssueID, ComicID): myDB = db.DBConnection() issue = myDB.action('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone() + annchk = 'no' + if issue is None: + if mylar.ANNUALS_ON: + issue = myDB.action('SELECT * FROM annuals WHERE IssueID=?', [IssueID]).fetchone() + annchk = 'yes' logger.info(u"Marking " + issue['ComicName'] + " issue # " + issue['Issue_Number'] + " as skipped...") controlValueDict = {'IssueID': IssueID} newValueDict = {'Status': 'Skipped'} - myDB.upsert("issues", newValueDict, controlValueDict) + if annchk == 'yes': + myDB.upsert("annuals", newValueDict, controlValueDict) + else: + myDB.upsert("issues", newValueDict, controlValueDict) raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % ComicID) unqueueissue.exposed = True def archiveissue(self, IssueID): myDB = db.DBConnection() issue = myDB.action('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone() + annchk = 'no' + if issue is None: + if mylar.ANNUALS_ON: + issue = myDB.action('SELECT * FROM annuals WHERE IssueID=?', [IssueID]).fetchone() + annchk = 'yes' logger.info(u"Marking " + issue['ComicName'] + " issue # " + issue['Issue_Number'] + " as archived...") controlValueDict = {'IssueID': IssueID} newValueDict = {'Status': 'Archived'} - myDB.upsert("issues", newValueDict, controlValueDict) + if annchk == 'yes': + myDB.upsert("annuals", newValueDict, controlValueDict) + else: + myDB.upsert("issues", newValueDict, controlValueDict) raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % issue['ComicID']) archiveissue.exposed = True @@ -683,6 +724,15 @@ class WebInterface(object): #upcoming = myDB.select("SELECT * from issues WHERE ReleaseDate > date('now') order by ReleaseDate DESC") upcoming = myDB.select("SELECT * from upcoming WHERE IssueDate > date('now') AND IssueID is NULL order by IssueDate DESC") issues = myDB.select("SELECT * from issues WHERE Status='Wanted'") + ann_list = [] + + if mylar.ANNUALS_ON: + #let's add the annuals to the wanted table so people can see them + #ComicName wasn't present in db initially - added on startup chk now. + annuals_list = myDB.select("SELECT * FROM annuals WHERE Status='Wanted'") + ann_list += annuals_list + issues += annuals_list + #let's move any items from the upcoming table into the wanted table if the date has already passed. #gather the list... mvupcome = myDB.select("SELECT * from upcoming WHERE IssueDate < date('now') order by IssueDate DESC") @@ -706,7 +756,7 @@ class WebInterface(object): deleteit = myDB.action("DELETE from upcoming WHERE ComicName=? AND IssueNumber=?", [mvup['ComicName'],mvup['IssueNumber']]) - return serve_template(templatename="upcoming.html", title="Upcoming", upcoming=upcoming, issues=issues) + return serve_template(templatename="upcoming.html", title="Upcoming", upcoming=upcoming, issues=issues, ann_list=ann_list) upcoming.exposed = True def skipped2wanted(self, comicid): @@ -886,13 +936,13 @@ class WebInterface(object): history.exposed = True def reOrder(request): - print ("I have reached the re-order!!!") - return serve_template(templatename="reorder.html", title="ReoRdered!", reorder=request) + return request +# return serve_template(templatename="reorder.html", title="ReoRdered!", reorder=request) reOrder.exposed = True def readlist(self): myDB = db.DBConnection() - readlist = myDB.select("SELECT * from readinglist group by StoryArcID COLLATE NOCASE") + readlist = myDB.select("SELECT * from readinglist WHERE ComicName is not Null group by StoryArcID COLLATE NOCASE") issuelist = myDB.select("SELECT * from readlist") readConfig = { "read2filename" : helpers.checked(mylar.READ2FILENAME), @@ -976,8 +1026,8 @@ class WebInterface(object): from xml.dom.minidom import parseString, Element import random myDB = db.DBConnection() - - file = open(str(filename)) + + file = open(filename) data = file.read() file.close() @@ -1472,8 +1522,8 @@ class WebInterface(object): def preSearchit(self, ComicName, comiclist=None, mimp=0): implog = '' - implog = implog + "imp_rename:" + str(imp_rename) + "\n" - implog = implog + "imp_move:" + str(imp_move) + "\n" + implog = implog + "imp_rename:" + str(mylar.IMP_RENAME) + "\n" + implog = implog + "imp_move:" + str(mylar.IMP_MOVE) + "\n" if mimp == 0: comiclist = [] comiclist.append(ComicName) @@ -1685,6 +1735,21 @@ class WebInterface(object): "newznab_api" : mylar.NEWZNAB_APIKEY, "newznab_enabled" : helpers.checked(mylar.NEWZNAB_ENABLED), "extra_newznabs" : mylar.EXTRA_NEWZNABS, + "enable_rss" : helpers.checked(mylar.ENABLE_RSS), + "rss_checkinterval" : mylar.RSS_CHECKINTERVAL, + "enable_torrents" : helpers.checked(mylar.ENABLE_TORRENTS), + "torrent_local" : helpers.checked(mylar.TORRENT_LOCAL), + "local_watchdir" : mylar.LOCAL_WATCHDIR, + "torrent_seedbox" : helpers.checked(mylar.TORRENT_SEEDBOX), + "seedbox_watchdir" : mylar.SEEDBOX_WATCHDIR, + "seedbox_host" : mylar.SEEDBOX_HOST, + "seedbox_port" : mylar.SEEDBOX_PORT, + "seedbox_user" : mylar.SEEDBOX_USER, + "seedbox_pass" : mylar.SEEDBOX_PASS, + "enable_torrent_search" : helpers.checked(mylar.ENABLE_TORRENT_SEARCH), + "enable_kat" : helpers.checked(mylar.ENABLE_KAT), + "enable_cbt" : helpers.checked(mylar.ENABLE_CBT), + "cbt_passkey" : mylar.CBT_PASSKEY, "destination_dir" : mylar.DESTINATION_DIR, "chmod_dir" : mylar.CHMOD_DIR, "chmod_file" : mylar.CHMOD_FILE, @@ -1777,6 +1842,28 @@ class WebInterface(object): myDB = db.DBConnection() #--- this is for multipe search terms............ #--- works, just need to redo search.py to accomodate multiple search terms + ffs_alt = [] + if '##' in alt_search: + ffs = alt_search.find('##') + ffs_alt.append(alt_search[:ffs]) + ffs_alt_st = str(ffs_alt[0]) + print ("ffs_alt: " + str(ffs_alt[0])) + + ffs_test = alt_search.split('##') + if len(ffs_test) > 0: + print("ffs_test names: " + str(len(ffs_test))) + ffs_count = len(ffs_test) + n=1 + while (n < ffs_count): + ffs_alt.append(ffs_test[n]) + print("adding : " + str(ffs_test[n])) + #print("ffs_alt : " + str(ffs_alt)) + ffs_alt_st = str(ffs_alt_st) + "..." + str(ffs_test[n]) + n+=1 + asearch = ffs_alt + else: + asearch = alt_search + # ffs_alt = [] # if '+' in alt_search: #find first + @@ -1868,7 +1955,8 @@ class WebInterface(object): use_nzbget=0, nzbget_host=None, nzbget_port=None, nzbget_username=None, nzbget_password=None, nzbget_category=None, nzbget_priority=None, usenet_retention=None, nzbsu=0, nzbsu_apikey=None, dognzb=0, dognzb_apikey=None, nzbx=0, newznab=0, newznab_host=None, newznab_name=None, newznab_apikey=None, newznab_enabled=0, raw=0, raw_provider=None, raw_username=None, raw_password=None, raw_groups=None, experimental=0, - enable_meta=0, cmtagger_path=None, + enable_meta=0, cmtagger_path=None, enable_rss=0, rss_checkinterval=None, enable_torrent_search=0, enable_kat=0, enable_cbt=0, cbt_passkey=None, + enable_torrents=0, torrent_local=0, local_watchdir=None, torrent_seedbox=0, seedbox_watchdir=None, seedbox_user=None, seedbox_pass=None, seedbox_host=None, seedbox_port=None, prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=None, nma_enabled=0, nma_apikey=None, nma_priority=0, nma_onsnatch=0, pushover_enabled=0, pushover_onsnatch=0, pushover_apikey=None, pushover_userkey=None, pushover_priority=None, preferred_quality=0, move_files=0, rename_files=0, add_to_csv=1, cvinfo=0, lowercase_filenames=0, folder_format=None, file_format=None, enable_extra_scripts=0, extra_scripts=None, enable_pre_scripts=0, pre_scripts=None, post_processing=0, syno_fix=0, search_delay=None, chmod_dir=0777, chmod_file=0660, cvapifix=0, destination_dir=None, replace_spaces=0, replace_char=None, use_minsize=0, minsize=None, use_maxsize=0, maxsize=None, autowant_all=0, autowant_upcoming=0, comic_cover_local=0, zero_level=0, zero_level_n=None, interface=None, **kwargs): @@ -1916,6 +2004,21 @@ class WebInterface(object): #mylar.NEWZNAB_HOST = newznab_host #mylar.NEWZNAB_APIKEY = newznab_apikey #mylar.NEWZNAB_ENABLED = newznab_enabled + mylar.ENABLE_RSS = int(enable_rss) + mylar.RSS_CHECKINTERVAL = rss_checkinterval + mylar.ENABLE_TORRENTS = int(enable_torrents) + mylar.TORRENT_LOCAL = int(torrent_local) + mylar.LOCAL_WATCHDIR = local_watchdir + mylar.TORRENT_SEEDBOX = int(torrent_seedbox) + mylar.SEEDBOX_WATCHDIR = seedbox_watchdir + mylar.SEEDBOX_HOST = seedbox_host + mylar.SEEDBOX_PORT = seedbox_port + mylar.SEEDBOX_USER = seedbox_user + mylar.SEEDBOX_PASS = seedbox_pass + mylar.ENABLE_TORRENT_SEARCH = int(enable_torrent_search) + mylar.ENABLE_KAT = int(enable_kat) + mylar.ENABLE_CBT = int(enable_cbt) + mylar.CBT_PASSKEY = cbt_passkey mylar.PREFERRED_QUALITY = int(preferred_quality) mylar.MOVE_FILES = move_files mylar.RENAME_FILES = rename_files @@ -1969,11 +2072,12 @@ class WebInterface(object): #changing this for simplicty - adding all newznabs into extra_newznabs if newznab_host is not None: #this - mylar.EXTRA_NEWZNABS.append((newznab_host, newznab_apikey, int(newznab_enabled))) + mylar.EXTRA_NEWZNABS.append((newznab_host, newznab_apikey, int(newznab_enabled), newznab_name)) for kwarg in kwargs: - if kwarg.startswith('newznab_host'): + if kwarg.startswith('newznab_name'): newznab_number = kwarg[12:] + newznab_name = kwargs['newznab_name' + newznab_number] newznab_host = kwargs['newznab_host' + newznab_number] newznab_api = kwargs['newznab_api' + newznab_number] try: @@ -1981,7 +2085,7 @@ class WebInterface(object): except KeyError: newznab_enabled = 0 - mylar.EXTRA_NEWZNABS.append((newznab_host, newznab_api, newznab_enabled)) + mylar.EXTRA_NEWZNABS.append((newznab_name, newznab_host, newznab_api, newznab_enabled)) # Sanity checking if mylar.SEARCH_INTERVAL < 360: @@ -1992,6 +2096,10 @@ class WebInterface(object): logger.info("Minimum search delay set for 1 minute to avoid hammering.") mylar.SEARCH_DELAY = 1 + if mylar.RSS_CHECKINTERVAL < 20: + logger.info("Minimum RSS Interval Check delay set for 20 minutes to avoid hammering.") + mylar.RSS_CHECKINTERVAL = 20 + if not helpers.is_number(mylar.CHMOD_DIR): logger.info("CHMOD Directory value is not a valid numeric - please correct. Defaulting to 0777") mylar.CHMOD_DIR = '0777' diff --git a/mylar/weeklypull.py b/mylar/weeklypull.py index 34699182..d6d88267 100755 --- a/mylar/weeklypull.py +++ b/mylar/weeklypull.py @@ -457,6 +457,7 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None): sqlsearch = re.sub("\\bTHE\\b", '', sqlsearch) if '+' in sqlsearch: sqlsearch = re.sub('\+', '%PLUS%', sqlsearch) sqlsearch = re.sub(r'\s', '%', sqlsearch) + sqlsearch = sqlsearch + '%' logger.fdebug("searchsql: " + sqlsearch) weekly = myDB.select('SELECT PUBLISHER, ISSUE, COMIC, EXTRA, SHIPDATE FROM weekly WHERE COMIC LIKE (?)', [sqlsearch]) #cur.execute('SELECT PUBLISHER, ISSUE, COMIC, EXTRA, SHIPDATE FROM weekly WHERE COMIC LIKE (?)', [lines[cnt]]) @@ -505,6 +506,10 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None): #logger.fdebug("modcomicnm:" + modcomicnm) #logger.fdebug("modwatchcomic:" + modwatchcomic) + #annuals! + if 'ANNUAL' in comicnm.upper(): + modcomicnm = re.sub("\\bANNUAL\\b", "", modcomicnm.upper()) + watchcomic = re.sub(r'\s', '', watchcomic) comicnm = re.sub(r'\s', '', comicnm) modwatchcomic = re.sub(r'\s', '', modwatchcomic) @@ -514,9 +519,9 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None): if comicnm == watchcomic.upper() or modcomicnm == modwatchcomic.upper(): logger.fdebug("matched on:" + comicnm + "..." + watchcomic.upper()) pass - elif ("ANNUAL" in week['EXTRA']): - pass - #print ( row[3] + " matched on ANNUAL") +# elif ("ANNUAL" in week['EXTRA']): +# pass +# print ( row[3] + " matched on ANNUAL") else: break if ("NA" not in week['ISSUE']) and ("HC" not in week['ISSUE']): @@ -529,9 +534,11 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None): #kp.append(row[0]) #ki.append(row[1]) #kc.append(comicnm) - if ("ANNUAL" in week['EXTRA']): + if "ANNUAL" in comicnm.upper(): watchfndextra.append("annual") + ComicName = str(unlines[cnt]) + " Annual" else: + ComicName = str(unlines[cnt]) watchfndextra.append("none") watchfnd.append(comicnm) watchfndiss.append(week['ISSUE']) @@ -541,7 +548,7 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None): else: ComicIssue = str(watchfndiss[tot -1]) ComicDate = str(week['SHIPDATE']) - ComicName = str(unlines[cnt]) + #ComicName = str(unlines[cnt]) logger.fdebug("Watchlist hit for : " + ComicName + " ISSUE: " + str(watchfndiss[tot -1])) # here we add to comics.latest updater.latest_update(ComicID=ComicID, LatestIssue=ComicIssue, LatestDate=ComicDate)
Timestamp
${item['ReadingOrder']} ${item['StoryArc']} ${item['ComicName']} (${item['SeriesYear']})
${issue['ComicName']}${issue['Issue_Number']} + <% + if any(d['IssueID'] == str(issue['IssueID']) for d in ann_list): + adjcomicname = issue['ComicName'] + ' Annual' + else: + adjcomicname = issue['ComicName'] + endif + %> + ${adjcomicname}${issue['Issue_Number']} ${issue['IssueDate']}
${upcome['ComicName']}${upcome['IssueNumber']}${upcome['DisplayComicName']}${upcome['IssueNumber']} ${upcome['IssueDate']} ${upcome['Status']}