tree checksum vpatch file split hunks
all signers: lobbes bvt diana_coman asciilifeform
antecedents: search_all_chans.kv hide_inactive.kv znc2tmsr_etc.kv navbar_date_auto.kv
press order:
patch:
(17 . 3)(17 . 4)
5 640165 hide_inactive asciilifeform "Configurable default-hide of idle chans"
6 641046 search_all_chans asciilifeform "Button to search in all logged chans"
7 641484 navbar_date_auto asciilifeform "Automatically skip empty days in navbar. Handle 'dawn of time' case."
8 641773 searchpg_oldlinks asciilifeform "Paginated search; automatic replacement of ancient logger link targets; fix for unicode barf in eat_dump.py."
- 77626555D2A7AC7388C19298A36A8E412B809C6BE8532703F18D1E41C197A41A5B3FBC76E964BBD4627B8BB09E3B98CD3EE31BCFB677EA90C1FB3AD9CA8DAC4F(159 . 3)(159 . 11)
13 (1) Automatically skip empty days in date navigation bar. At the same time, handle empty days correctly when these are requested.
14 (2) Handle 'dawn of time' case for any given channel, to avoid infinite loop insanity from search engines.
15
16 ####################
17 Aug. 2020 Update :
18 ####################
19
20 (1) Implemented fetch-by-channel-and-index (i.e. /ilog/chan/lineindex links).
21 (2) Automatically adjust link targets of #ba and 'btcbase' log citations to point to this logger, using the syntax in (1). Original text of link is preserved. Dates are handled correctly.
22 (3) Search results now properly paginated, with working 'back' and 'forward' buttons.
23 (4) Fixed ancient unicode bug in eat_dump.py.
- E2818C8381E2A08187A2B3859FE79AC92E2694F14D9214C3FC008E52A48DBE2BB17B40601C30950D3035BBB892B21D2C83D1AB1A45BB595CD1E3EBAF26C97CBA(69 . 15)(69 . 17)
28 self_speak = True
29
30 ## Handle uniturds using the phf algorithm
31 payload = payload.decode('latin-1')
32 payload = payload.encode('utf-8')
33 try:
34 payload = payload.decode("utf-8")
35 except UnicodeDecodeError:
36 payload = payload.decode('latin-1')
37
38 ## Put in DB:
39 try:
40 exec_db('''insert into loglines (idx, t, chan, era, speaker, self, payload)
41 values (%s, %s, %s, %s, %s, %s, %s) ; ''',
42 [int(idx), datetime.fromtimestamp(time), str(chan), int(era), str(speaker),
43 bool(self_speak), str(payload)])
44 bool(self_speak), payload])
45 commit_db()
46 except psycopg2.IntegrityError as e:
47 rollback_db()
- 3FB19192427A44DCB19DF8673EABEF04A84355B0A7BEC3A411ADFEF6B7199969EAF2C02F8536CA89FF5C0332110574C47FF804B323543BEDD21353D0FF855D7D(61 . 6)(61 . 9)
52 # Days of inactivity after which chan is hidden by default
53 days_hide = 14
54
55 # Max # of search results per page
56 max_search = 500
57
58 # On what port will sit the www logtron
59 www_port = 5002
60
- A56AF711977A55E1332E0A42D8E2ACFDFB7C2D9DB72DC86C276949C337F0E66ACBE6455B19CB156FABB1B242BC7C7F8A69E48987F20D745BCBF44E60D52E9B46(55 . 6)(55 . 7)- 2B005C8DC669CD7229E8A3CB3932D0B53B7E49FE8D1C7E6A5C33192F81E0937F21324307473A24F7670EB3FF82FB2147DAB48B3B8C3E902F25937AFC1DCA5783
65 Days_Hide = int(cfg.get("logotron", "days_hide"))
66 # WWW:
67 WWW_Port = int(cfg.get("logotron", "www_port"))
68 Max_Search_Results = int(cfg.get("logotron", "max_search"))
69
70 except Exception as e:
71 print "Invalid config: ", e
(66 . 7)(67 . 6)
73 ### Knobs not made into config yet ###
74 Default_Chan = Channels[0]
75 Min_Query_Length = 3
76 Max_Search_Results = 1000
77
78 ## Format for Date in Log Lines
79 Date_Short_Format = "%Y-%m-%d"
(247 . 6)(247 . 12)
81
82 stdlinks_re = re.compile('(http[^ \[\]]+)')
83
84 # For era 1 ('bitcoin-assets') links :
85 era1_re = re.compile('(<a href="http[^ \[\]]\/\/log\d*\.bitcoin-assets\.com\/\?date=\d+-\d+-\d+#)(\d+)')
86
87 # For era 2 ('btcbase') links :
88 era2_re = re.compile('(<a href="http[^ \[\]]\/\/btcbase\.org\/log\/\d+-\d+-\d+#)(\d+)')
89
90
91 ## Format given log line for display
92 def format_logline(l, highlights = [], select=[], showchan=False):
(259 . 7)(265 . 18)
94 # Now also format [link][text] links :
95 payload = re.sub(boxlinks_re,
96 r'<a href="\1" target=\'_blank\'>\2</a>', payload)
97
98
99 # For ancient logs strictly: substitute orig. link with our logger :
100 if l['era'] < 3:
101 payload = re.sub(era1_re,
102 r'<a href="/ilog/{0}/\2'.format(l['chan']),
103 payload)
104
105 # Adjust era 2 links in all cases:
106 payload = re.sub(era2_re,
107 r'<a href="/ilog/{0}/\2'.format(l['chan']),
108 payload)
109
110 # If this is a search result, illuminate the matched strings:
111 if highlights != []:
112 payload = highlight_text(highlights, payload)
(407 . 6)(424 . 30)
114 idle_day = Days_Hide)
115
116
117 # Primarily for use with 'era 1' and 'era 2' :
118 # Get arbitrary log item by chan and raw line index
119 @app.route('/ilog/<chan>/<idx>')
120 def ilog(chan, idx):
121 # Handle rubbish chan:
122 if chan not in Channels:
123 return redirect(url_for('log'))
124
125 # Attempt to locate given chan/idx:
126 item = query_db(
127 '''select * from loglines where chan=%s and idx = %s ;''',
128 [chan, idx], one=True)
129
130 # If given chan/idx not found:
131 if item == None:
132 return redirect(url_for('log'))
133
134 # Determine date where item appears in log :
135 item_date = item['t'].strftime(Date_Short_Format)
136
137 # Go there:
138 return redirect("/log/" + chan + "/" + item_date + "#" + idx)
139
140
141 @app.route('/log-raw/<chan>')
142 def rawlog(chan):
143 res = ""
(467 . 8)(508 . 8)
145 # The query params:
146 chan = request.args.get('chan', default = Default_Chan, type = str)
147 query = request.args.get('q', default = '', type = str)
148 # page_num = request.args.get('page', default = 0, type = int)
149
150 offset = request.args.get('after', default = 0, type = int)
151
152 # channels to search in
153 chans = []
154
(515 . 32)(556 . 50)
156 if from_users == []:
157 searchres = query_db(
158 '''select * from loglines where chan = any(%s)
159 and payload ilike all(%s) order by t desc limit %s;''',
160 and payload ilike all(%s) order by t desc
161 limit %s offset %s;''',
162 [(chans,),
163 tokens_formed,
164 Max_Search_Results], one=False)
165 Max_Search_Results,
166 offset], one=False)
167 else:
168 searchres = query_db(
169 '''select * from loglines where chan = any(%s)
170 and speaker ilike any(%s)
171 and payload ilike all(%s) order by t desc limit %s;''',
172 and payload ilike all(%s) order by t desc
173 limit %s offset %s;''',
174 [(chans,),
175 from_users,
176 tokens_formed,
177 Max_Search_Results], one=False)
178
179
180 # Number of entries found
181 Max_Search_Results,
182 offset], one=False)
183
184 # Number of search results returned in this query
185 nres = len(searchres)
186 search_head = "<b>{0}</b> entries found in {1} for <b>'{2}'</b> :".format(
187 nres, legend, html_escape(query))
188
189
190 # Whether to display 'back' button :
191 back = (offset != 0)
192
193 # Whether to display 'forward' button :
194 forw = (nres == Max_Search_Results)
195
196 # Starting index of search results
197 sres = offset
198
199 # Ending index of search results
200 eres = offset + min(nres, Max_Search_Results)
201
202 # No paging support just yet:
203 return render_template('searchres.html',
204 query = query,
205 nres = nres,
206 hquery = html_escape(query),
207 legend = legend,
208 sres = sres,
209 eres = eres,
210 back = back,
211 forw = forw,
212 psize = Max_Search_Results,
213 chan = chan,
214 search_head = search_head,
215 tokens = tokens_orig,
216 loglines = searchres,
217 showchan = showchan)
(1 . 12)(1 . 20)
222 {% extends "layout.html" %}
223
224 {% block title %}
225 {{ nres }} Results for {{ query }} in #{{ chan }}
226 Results {{ sres }} ... {{ eres }} for {{ query }} in {{ legend }}
227 {% endblock %}
228
229 {% block body %}
230
231 <div align="center"><span>{{ search_head | safe }}</span></div>
232 <div id="navbarblock">
233 <div align="center"><span>
234 {% if back %}<a href="/log-search?q={{ query }}&chan={{ chan }}&after={{ sres - psize }}">←</a> | {% endif %}
235 Results <b>{{ sres + 1 }} ... {{ eres }}</b> found in {{ legend | safe }} for <b>'{{ hquery }}'</b> :{% if forw %} |
236 <a href="/log-search?q={{ query }}&chan={{ chan }}&after={{ eres }}">→</a>
237 {% endif %}
238 </span></div>
239 </div>
240 <div style="clear: both;"></div>
241
242 <hr>
243