noticesys 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dd1393e55e8b90efda85d824f9a9ee9111a2802386c663e25f4b96e1f894cd6
4
- data.tar.gz: add7a94854c0dd48d711772c8aa703731bf6d36484289be76a25f55cd6872827
3
+ metadata.gz: dc57ed6739da60187b8cc0ef1e4da8a1cc80ac45c7d61457d06dfdd1d41b1879
4
+ data.tar.gz: c6766e6a31a2cef0597d16ff710ef60ab4f85a0e3b93a6bdba43f245d5272e93
5
5
  SHA512:
6
- metadata.gz: b521dc650d991b843ab5977b8150e8ad9809f5a11fc09d2afe8fa853cc5ee40e6def90a0ddcfb6718d12096738a2c16c44995093aff8491fe3ace6e6c852410f
7
- data.tar.gz: 75357c37d9d1c8de344e3227a466e0345d96350b53a844dc2daf82b32f773715dbdcff1f2025f8397a0c51761aa6802823435c79ed4bdd184af17b45ab0c344f
6
+ metadata.gz: d9f242c894cb5cfd50618f8035cfe71404584d846f99b0bcc43d3ee32428d895c669ea2d6f5a64b2afc3771719a1d1519747b3b0e1a25ddcdbf4070a5a6f3e40
7
+ data.tar.gz: 95b74880b300da703559a865c3ae1c916d6123f5437af2ad0cdeed65696602454ab3a901cb2a59a52bcd61ca0af35e9fe6c3577afb3e88fd48fd53d806f2da0a
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -0,0 +1,182 @@
1
+ %card
2
+
3
+ <div class='card'>
4
+ <a href='#{url}' target='_blank'>
5
+ <div class='top-crop center'>
6
+ <img src='#{img}'/>
7
+ </div>
8
+ <span class='title'>#{title}</span>
9
+ <span class='desc'>#{desc}</span>
10
+ <span class='link'>
11
+
12
+ <:svg/link>
13
+
14
+ <span class='linkurl'>#{site}</span>
15
+ </span>
16
+ </a>
17
+ </div>
18
+
19
+ %card2
20
+
21
+ <div class="card2">
22
+ <a href="#{url}" target="_blank">
23
+ <div>
24
+ <div id='col1'>
25
+ #{img_element}
26
+ </div>
27
+ <div id='col2'>
28
+ <div id='content'>
29
+ <span class="title">#{title}</span>
30
+ <span class="desc">#{desc}</span>
31
+ <span class="link">
32
+ <:svg/link>
33
+ <span class="linkurl">#{site}</span>
34
+ </span>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </a>
39
+ </div>
40
+
41
+
42
+ %meta
43
+ <meta name="twitter:card" content="#{type}"/>
44
+ <meta name="twitter:title" property="og:title" content="#{h[:title]}"/>
45
+ <meta name="twitter:image" property="og:image" content="#{img}"/>
46
+ <meta name="twitter:description" property="og:descrtiption" content="#{h[:desc]}"/>
47
+ <meta property="og:url" content="#{h[:url]}"/>
48
+ <meta name="noticesys:card" content="notice"/>
49
+
50
+ %notice
51
+
52
+ <div class='notice'>
53
+ <div id='avatar' class='profile'>
54
+ <a href="/#{rx.topic}"><img src='#{dx.image}'/></a>
55
+ <div id='ucard'>
56
+ <div>
57
+ <img src='#{dx.image}'/>
58
+ </div>
59
+ <a href="/#{rx.topic}"><span class='title'>#{dx.title}</span></a>
60
+ <span class='username'>@#{username}</span>
61
+ <p>#{dx.bio}</p>
62
+
63
+ </div>
64
+ </div>
65
+ <div class='ncol2'>
66
+ <div class='user'><a href="#{rx.topic}"><span>#{dx.title}</span></a> @#{rx.topic} &middot; <a href="#{rx.link}" title="#{d}">#{relative_time
67
+ }</a><:svg/ellipsis>
68
+ </div>
69
+
70
+ #{description}
71
+ #{card2}
72
+ <div id='actions'>
73
+ <:svg/reply>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ %status
79
+
80
+ <html>
81
+ <head>
82
+ <title>#{dx.title}</title>
83
+ <meta charset='UTF-8'/>
84
+ <meta name='viewport' content='width=device-width, initial-scale=1'/>
85
+ #{meta}
86
+ <link rel='stylesheet' type='text/css' href='#{@css_url}'/>
87
+ </head>
88
+ <body>
89
+ <header>
90
+ <div>
91
+ #{back}
92
+ <div><h1>Notice</h1></div>
93
+ </div>
94
+ </header>
95
+ #{e.xml}
96
+ </body>
97
+ </html>
98
+
99
+ %user
100
+
101
+ <html>
102
+ <head>
103
+ <title>#{dx.title} (@#{username}) | Microblog</title>
104
+ <meta charset='UTF-8'/>
105
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
106
+ <link rel='stylesheet' type='text/css' href='#{@css_url}'/>
107
+
108
+ </head>
109
+ <body>
110
+ <div id='wrap' class='main'>
111
+ <header>
112
+ <div id='banner'>
113
+
114
+ </div>
115
+ <div id='search'>
116
+ <form action='/search'>
117
+ <input type='text' name='q' id='q' placeholder='Search microblogs'/>
118
+ </form>
119
+ </div>
120
+ </header>
121
+ <div style='clear: both'/>
122
+ <div class='row'>
123
+ <div class='column'>
124
+
125
+ </div>
126
+ <div class='column'>
127
+ #{s}
128
+
129
+ </div>
130
+ <div class='column'>
131
+ <h2>Currently</h2>
132
+
133
+ </div>
134
+ </div>
135
+ <div id='footer'>
136
+ <h2>Links</h2>
137
+ <ul>
138
+ <li><a href='about:blank'>blank</a></li>
139
+ </ul>
140
+ </div>
141
+ </div>
142
+ </body>
143
+ </html>
144
+
145
+ %ptop
146
+
147
+ <div id='ptop'>
148
+ <img src='#{dx.image}'/>
149
+ <span id='title'>#{dx.title}</span>
150
+ <span id='user'>@#{username}</span>
151
+ <p>#{dx.bio}</p>
152
+ </div>
153
+
154
+ <hr/>
155
+
156
+ %rsslink
157
+
158
+ <hr/>
159
+ <a href="//#{@static_urlbase}/microblog/u/#{username}/rss.xml">rss</a>
160
+
161
+ %svg
162
+ %article
163
+
164
+ <svg viewBox="0 0 24 24" class="r-m0bqgq r-4qtqp9 r-yyyyoo r-yucp9h r-dnmrzs r-bnwqim r-1plcrui r-lrvibr"><g><path d="M14 11.25H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm0-4H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm-3.25 8H6c-.414 0-.75.336-.75.75s.336.75.75.75h4.75c.414 0 .75-.336.75-.75s-.336-.75-.75-.75z"></path><path d="M21.5 11.25h-3.25v-7C18.25 3.01 17.24 2 16 2H4C2.76 2 1.75 3.01 1.75 4.25v15.5C1.75 20.99 2.76 22 4 22h15.5c1.517 0 2.75-1.233 2.75-2.75V12c0-.414-.336-.75-.75-.75zm-18.25 8.5V4.25c0-.413.337-.75.75-.75h12c.413 0 .75.337.75.75v15c0 .452.12.873.315 1.25H4c-.413 0-.75-.337-.75-.75zm16.25.75c-.69 0-1.25-.56-1.25-1.25v-6.5h2.5v6.5c0 .69-.56 1.25-1.25 1.25z"></path></g></svg>
165
+
166
+ %backarrow
167
+
168
+ <svg viewBox="0 0 24 24" class="backarrow"><g><path d="M20 11H7.414l4.293-4.293c.39-.39.39-1.023 0-1.414s-1.023-.39-1.414 0l-6 6c-.39.39-.39 1.023 0 1.414l6 6c.195.195.45.293.707.293s.512-.098.707-.293c.39-.39.39-1.023 0-1.414L7.414 13H20c.553 0 1-.447 1-1s-.447-1-1-1z"></path></g></svg>
169
+
170
+ %ellipsis
171
+
172
+ <svg viewBox="0 0 24 24" class="ellipsis"><g><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></g></svg>
173
+
174
+
175
+ %link
176
+
177
+ <svg viewBox="0 0 24 24"><g><path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z"></path><path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z"></path></g></svg>
178
+
179
+ %reply
180
+
181
+ <svg viewBox="0 0 24 24" <g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>
182
+
data/lib/noticesys.rb CHANGED
@@ -3,15 +3,28 @@
3
3
  # file: noticesys.rb
4
4
 
5
5
  require 'down' # file downloader
6
+ require 'weblet' # HTML retrieval
7
+ require 'dynarex' # flat file storage system
8
+ require 'unichron' # universal chron tool (i.e. time calculation)
6
9
  require 'ogextractor' # extract metadata
10
+ require 'recordx_sqlite'
7
11
 
8
12
 
13
+ # classes:
14
+ #
15
+ # Client - sends the msg to the messaging broker
16
+ # StatusView - renders the HTML for a user status
17
+ # StatusListView - renders the HTML for a user timeline
18
+ # CardView - renders the HTML for a card; used within a status
19
+ # HashtagQueryView - renders the HTML for the results for a hashtag search
20
+ # SearchQueryView - renders the HTML for the results for a keyword search
21
+
9
22
  module NoticeSys
10
23
 
11
24
  class Client
12
25
 
13
- def initialize(user='', rmagick=nil)
14
- @user, @rmagick = user, rmagick
26
+ def initialize(user='', rmagick=nil, debug: false)
27
+ @user, @rmagick, @debug = user, rmagick, debug
15
28
  end
16
29
 
17
30
  # params expected: msg, file1, file2, file3
@@ -39,16 +52,21 @@ module NoticeSys
39
52
 
40
53
  h2 = OgExtractor.new(urls.last).to_h
41
54
 
55
+ puts 'h2: ' + h2.inspect if @debug
56
+
42
57
  if h2 then
43
58
  h = {msg: msg, files: files}
44
59
 
45
60
  h[:site]= h2[:url][/https?:\/\/([^\/]+)/,1].sub(/^www\./,'')
46
61
 
47
- tmpfile = Down.download h2[:img]
48
- files2 = scale_img tmpfile.to_path
62
+ if h2[:img] then
63
+ tmpfile = Down.download h2[:img]
64
+ files2 = scale_img tmpfile.to_path
65
+ end
49
66
 
50
- h[:files] = files2
51
- h[:card] = {h2[:card] => { title: h2[:title], desc: h2[:desc], url: h2[:url]}}
67
+ h[:files] = files2 || []
68
+ h[:card] = {h2[:card] => { title: h2[:title], desc: h2[:desc],
69
+ url: h2[:url]}}
52
70
  h[:msg] = msg.sub(urls.last,'')
53
71
 
54
72
  return "notice/%s/json: %s" % [@user, h.to_json]
@@ -118,5 +136,465 @@ module NoticeSys
118
136
  end
119
137
 
120
138
  end
139
+
140
+
141
+ class CardView
142
+
143
+ def initialize(weblet)
144
+
145
+ @w = weblet
146
+
147
+ end
148
+
149
+ def render(dx, rx, card)
150
+
151
+ card2 = case card.keys.first
152
+ when :images
153
+
154
+ card[:images].map.with_index do |img, i|
155
+
156
+ href = [dx.link.sub(/\/$/,''), rx.topic, 'status', rx.id,
157
+ 'photo', (i+1).to_s ].join('/')
158
+ url, align = img[:url], img[:align]
159
+ "<a href='%s'><div class='top-crop %s'><img class='img1' src='%s'/></div></a>" % [href, align, url]
160
+
161
+ end.join
162
+
163
+ when :summary_large_image
164
+
165
+ h2 = card[:summary_large_image]
166
+
167
+ rawdesc = h2[:desc]
168
+
169
+ desc = rawdesc.length > 147 ? rawdesc[0..147] + '...' : rawdesc
170
+ site = h2[:url][/https?:\/\/([^\/]+)/,1].sub(/^www\./,'')
171
+ title = h2[:title]
172
+ img = h2[:img]
173
+ url = h2[:url]
174
+
175
+ @w.render('card', binding)
176
+
177
+ when :summary
178
+
179
+ h2 = card[:summary]
180
+
181
+ rawdesc = h2[:desc]
182
+
183
+ desc = rawdesc.length > 95 ? rawdesc[0..95] + '...' : rawdesc
184
+ site = h2[:url][/https?:\/\/([^\/]+)/,1].sub(/^www\./,'')
185
+ title = h2[:title].length > 46 ? h2[:title][0..46] + '...' : h2[:title]
186
+ img = h2[:img]
187
+ url = h2[:url]
188
+
189
+ img_element = if img then
190
+ "<img src='#{img}'>"
191
+ else
192
+ @w.render('svg/article')
193
+ end
194
+
195
+ @w.render('card2', binding)
196
+
197
+ end
198
+ end
199
+ end
200
+
201
+ class StatusView
202
+
203
+ def initialize(basepath, xslfile, css_url, weblet)
204
+
205
+ @basepath, @xslfile, @css_url = basepath, xslfile, css_url
206
+ @w = weblet
207
+ @card = CardView.new(@w)
208
+
209
+ end
210
+
211
+ def render(topic, rawid, referer)
212
+
213
+ id = rawid[0..9].to_i
214
+
215
+ filepath = File.join(@basepath, 'u', topic)
216
+ a = [Time.at(id).strftime("%Y/%b/%-d").downcase, rawid]
217
+ xmlfile = File.join(filepath, "%s/%s/index.xml" % a)
218
+ xslfile = File.join(@basepath, "/xsl/notices/#{topic}.xsl")
219
+
220
+ unless File.exists? xslfile then
221
+ xslfile = @xslfile
222
+ end
223
+
224
+ dx = Dynarex.new(File.join(filepath, 'feed.xml'))
225
+ doc = Rexle.new(File.read(xmlfile))
226
+
227
+ doc.root.element('summary/title').text = dx.title
228
+ e = doc.root.element('summary/image')
229
+
230
+ if e.nil? then
231
+ e = Rexle::Element.new 'image'
232
+ doc.root.element('summary').add e
233
+ end
234
+
235
+ doc.root.element('summary/image').text = dx.image
236
+
237
+ # remove the card from the description
238
+ desc = doc.root.element('body/description')
239
+ desc.xpath('img|div').each(&:delete)
240
+
241
+ doc = Nokogiri::XML(doc.root.xml)
242
+ xslt = Nokogiri::XSLT(File.read(xslfile))
243
+
244
+ s = xslt.transform(doc)
245
+ doc = Rexle.new(s.to_s)
246
+
247
+ rx = Kvx.new(xmlfile)
248
+
249
+ rawcard = rx.card
250
+
251
+
252
+ card2, meta = if rawcard and rawcard.length > 10 then
253
+
254
+ card = JSON.parse(rawcard, symbolize_names: true)
255
+
256
+ if card.is_a? Hash then
257
+
258
+ type = card.keys.first
259
+ h = card[type]
260
+ #img = h[:img].sub(/small(?=\.\w+$)/,'large')
261
+ img = h[:img]
262
+ metadata = @w.render(:meta, binding)
263
+ [@card.render(dx, rx, card), metadata]
264
+
265
+ end
266
+ else
267
+ '<span/>'
268
+ end
269
+
270
+
271
+ e = doc.root.at_css '#notice'
272
+ desc = e.at_css '#desc'
273
+ desc.add Rexle.new(card2).root
274
+
275
+ ref = referer
276
+ svg = @w.render 'svg/backarrow', binding
277
+
278
+ back = if ref then
279
+ "<div id='back'><a href='#{ref}' title='back'>#{svg}</a></div>"
280
+ else
281
+ ''
282
+ end
283
+
284
+ @w.render :status, binding
285
+
286
+ end
287
+
288
+ end
289
+
290
+ class NoticeView
291
+
292
+ def render()
293
+ end
294
+
295
+ end
296
+
297
+
298
+ class StatusListView
299
+
300
+ def initialize(basepath, css_url, static_urlbase, weblet)
301
+
302
+ @basepath, @css_url, @static_urlbase = basepath, css_url, static_urlbase
303
+ @w = weblet
304
+ @card = CardView.new(@w)
305
+
306
+ end
307
+
308
+ def render(username)
309
+
310
+ s = ''
311
+
312
+ dx = Dynarex.new(File.join(@basepath, 'u', username, 'feed.xml'))
313
+
314
+ s += @w.render 'user/ptop', binding
315
+
316
+ notices = dx.all.map do |rx|
317
+
318
+ card2 = ''
319
+ rawcard = rx.to_h[:card]
320
+
321
+ card2 = if rawcard and rawcard.length > 10 then
322
+
323
+ card = JSON.parse(rawcard, symbolize_names: true)
324
+
325
+ if card.is_a? Hash then
326
+ @card.render(dx, rx, card)
327
+ end
328
+
329
+ else
330
+ ''
331
+ end
332
+
333
+ t2 = Time.at rx.id.to_s[0..9].to_i
334
+ relative_time = Unichron.new(t2).elapsed
335
+
336
+ d = t2.strftime("%I:%M%p %b %d %Y")
337
+
338
+ description = if rx.description.length > 1 then
339
+ doc = Rexle.new "<node>%s</node>" % rx.description.gsub(/<\/?p>/,'')
340
+ doc.root.xpath('img|div').each(&:delete)
341
+ "<p>%s</p>" % doc.root.xml
342
+ else
343
+ ''
344
+ end
345
+
346
+ utitle, uimage, ubio = dx.title, dx.image, dx.bio
347
+ @w.render :notice, binding
348
+
349
+ end
350
+
351
+ s += notices.join
352
+ s += @w.render 'user/rsslink', binding
353
+ @w.render :user, binding
354
+
355
+ end
356
+ end
357
+
358
+ class HashtagQueryView
359
+
360
+ def initialize(basepath, css_url, weblet, static_urlbase, urlbase)
361
+
362
+ @basepath, @css_url, @static_urlbase = basepath, css_url, static_urlbase
363
+ @w, @urlbase = weblet, urlbase
364
+ @card = CardView.new(@w)
365
+
366
+ end
367
+
368
+ def render(q, referer)
369
+ #q = args.first
370
+ dbpath = File.join(@basepath, '/hashtag/index.db')
371
+ db = RecordxSqlite.new(dbpath, table: 'hashtags')
372
+
373
+
374
+ a = db.find_all_by_tag q
375
+
376
+ topics = a.map(&:topic).uniq.map do |topic|
377
+
378
+ topicpath = File.join(@basepath, 'u', topic)
379
+ filepath = File.join(topicpath, "notices.db")
380
+ db = RecordxSqlite.new(filepath, table: 'notices')
381
+
382
+ dx = Dynarex.new(File.join(topicpath, 'feed.xml'))
383
+ [topic, OpenStruct.new(title: dx.title, image: dx.image, db: db)]
384
+
385
+ end.to_h
386
+
387
+
388
+ rows = a.map do |x|
389
+
390
+ r = topics[x.topic]
391
+ rx = r.db.find x.noticeid
392
+ link = "%s/%s/status/%s" % [@urlbase, x.topic, x.noticeid]
393
+ OpenStruct.new(rx.to_h.merge({topic: x.topic, title: r.title,
394
+ image: r.image, bio: r.bio, link: link}))
395
+
396
+ end
397
+
398
+
399
+ s = ''
400
+
401
+ notices = rows.sort_by {|x| -(x.id.to_i)}.take(20).map do |rx|
402
+
403
+ next unless rx.description
404
+
405
+ card2 = ''
406
+ rawcard = rx.to_h[:card]
407
+
408
+ card2 = if rawcard and rawcard.length > 10 then
409
+
410
+ card = JSON.parse(rawcard, symbolize_names: true)
411
+
412
+ if card.is_a? Hash then
413
+ @card.render(dx, rx, card)
414
+ end
415
+
416
+ else
417
+ ''
418
+ end
419
+
420
+ t2 = Time.at rx.id.to_s[0..9].to_i
421
+ relative_time = Unichron.new(t2).elapsed
422
+
423
+ d = t2.strftime("%I:%M%p %b %d %Y")
424
+
425
+ description = if rx.description.length > 1 then
426
+ doc = Rexle.new "<node>%s</node>" % rx.description.gsub(/<\/?p>/,'')
427
+ doc.root.xpath('img|div').each(&:delete)
428
+ "<p>%s</p>" % doc.root.xml
429
+ else
430
+ ''
431
+ end
432
+
433
+ utitle, uimage, ubio = rx.title, rx.image, rx.bio
434
+ @w.render :notice, binding
435
+
436
+ end
437
+
438
+ s += if notices.any? then
439
+ notices.compact.join
440
+ else
441
+ "<p>No results for #{q}</p>"
442
+ end
443
+
444
+ ref = referer
445
+ ref = '../' if ref =~ /(?:status|hashtag)\/\d+/
446
+
447
+ svg = @w.render 'svg/backarrow', binding
448
+ back = ref ? "<a href='#{ref}'>#{svg}</a>" : ''
449
+
450
+ @w.render :search_pg, binding
451
+
452
+ end
453
+
454
+
455
+ end
456
+
457
+ class SearchQueryView
458
+
459
+ def initialize(basepath, css_url, weblet, static_urlbase, urlbase)
460
+
461
+ @basepath, @css_url, @static_urlbase = basepath, css_url, static_urlbase
462
+ @w, @urlbase = weblet, urlbase
463
+ @card = CardView.new(@w)
464
+
465
+ end
466
+
467
+ def render(q, referer)
468
+
469
+
470
+ users = Dir.glob(File.join(@basepath, 'u', '*')).map do |x|
471
+ File.basename(x)
472
+ end
473
+
474
+ topics = users.map do |topic|
475
+
476
+ topicpath = File.join(@basepath, 'u', topic)
477
+ filepath = File.join(topicpath, "notices.db")
478
+ db = RecordxSqlite.new(filepath, table: 'notices')
479
+
480
+ dx = Dynarex.new(File.join(topicpath, 'feed.xml'))
481
+ [topic, OpenStruct.new(title: dx.title, image: dx.image, bio: dx.bio, db: db)]
121
482
 
483
+ end.to_h
484
+
485
+ #return topics.inspect
486
+ rows = topics.flat_map do |topic, r|
487
+
488
+ a = r.db.all.select {|x| x.description =~ /#{q}/i}
489
+ a.map do |rx|
490
+ link = "%s/%s/status/%s" % [@urlbase, topic, rx.noticeid]
491
+ OpenStruct.new(rx.to_h.merge({topic: topic, title: r.title, image: r.image, link: link}))
492
+ end
493
+
494
+ end
495
+
496
+
497
+ #return rows.inspect
498
+ s = ''
499
+
500
+ notices = rows.sort_by {|x| -(x.id.to_i)}.take(20).map do |rx|
501
+
502
+
503
+ card2 = ''
504
+ rawcard = rx.to_h[:card]
505
+
506
+ card2 = if rawcard and rawcard.length > 10 then
507
+
508
+ card = JSON.parse(rawcard, symbolize_names: true)
509
+
510
+ if card.is_a? Hash then
511
+ @card.render(dx, rx, card)
512
+ end
513
+
514
+ else
515
+ ''
516
+ end
517
+
518
+ #rx.description
519
+ t2 = Time.at rx.id.to_s[0..9].to_i
520
+ relative_time = Unichron.new(t2).elapsed
521
+
522
+ d = t2.strftime("%I:%M%p %b %d %Y")
523
+
524
+ #desc = rx.description.gsub(/<\/?p>/,'').gsub('&lt;','<').gsub('&gt;','>')
525
+
526
+ topic = rx.topic
527
+ title, image, bio = %i(title image bio).map do |x|
528
+ topics[topic].method(x).call
529
+ end
530
+
531
+ description = if rx.description.length > 1 then
532
+ doc = Rexle.new "<node>%s</node>" % rx.description.gsub(/<\/?p>/,'')
533
+ doc.root.xpath('img|div').each(&:delete)
534
+ "<p>%s</p>" % doc.root.xml
535
+ else
536
+ ''
537
+ end
538
+
539
+ utitle, uimage, ubio = title, image, bio
540
+ @w.render :notice, binding
541
+
542
+
543
+ end
544
+ #return notices.inspect
545
+
546
+ s += if notices.any? then
547
+ notices.join
548
+ else
549
+ "<p>No results for #{q}</p>"
550
+ end
551
+
552
+ #ref = @env["HTTP_REFERER"]
553
+ ref = referer
554
+ ref = '../' if ref =~ /(?:status\/\d+|search)/
555
+ svg = @w.render 'svg/backarrow', binding
556
+ back = ref ? "<a href='#{ref}'>#{svg}</a>" : ''
557
+
558
+ @w.render :search_pg, binding
559
+
560
+
561
+ end
562
+
563
+
564
+ end
565
+
566
+ class Main
567
+
568
+ def initialize(basepath, xslfile, statuscss_url, statuslistcss_url,
569
+ weblet_file, static_urlbase, urlbase)
570
+
571
+ weblet = Weblet.new(weblet_file)
572
+ @status = StatusView.new(basepath, xslfile, statuscss_url, weblet)
573
+ @statuslist = StatusListView.new(basepath, statuslistcss_url,
574
+ static_urlbase, weblet)
575
+ @hashtag = HashtagQueryView.new(basepath, statuslistcss_url, weblet,
576
+ static_urlbase, urlbase)
577
+ @search = SearchQueryView.new(basepath, statuslistcss_url, weblet,
578
+ static_urlbase, urlbase)
579
+
580
+ end
581
+
582
+ def status(topic, rawid, referer)
583
+ @status.render topic, rawid, referer
584
+ end
585
+
586
+ def status_list(username)
587
+ @statuslist.render username
588
+ end
589
+
590
+ def hashtag_query(s, referer)
591
+ @hashtag.render s, referer
592
+ end
593
+
594
+ def search_query(s, referer)
595
+ @search.render s, referer
596
+ end
597
+
598
+ end
599
+
122
600
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noticesys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,7 +35,7 @@ cert_chain:
35
35
  iGAgDWBQqM/kdjDslqjBGtyWyFyuYHzXMU1gO/P0aE3rh1enqahZ8BqY+gxXLGrR
36
36
  sU+WFV9qPqoqNOG0tOknOZXN
37
37
  -----END CERTIFICATE-----
38
- date: 2021-04-02 00:00:00.000000000 Z
38
+ date: 2021-04-05 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: down
@@ -57,6 +57,66 @@ dependencies:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
59
  version: '5.2'
60
+ - !ruby/object:Gem::Dependency
61
+ name: weblet
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.3'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.3.3
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '0.3'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 0.3.3
80
+ - !ruby/object:Gem::Dependency
81
+ name: dynarex
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '1.8'
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.27
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.8'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 1.8.27
100
+ - !ruby/object:Gem::Dependency
101
+ name: unichron
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '0.3'
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 0.3.2
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.3'
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: 0.3.2
60
120
  - !ruby/object:Gem::Dependency
61
121
  name: ogextractor
62
122
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +126,7 @@ dependencies:
66
126
  version: '0.1'
67
127
  - - ">="
68
128
  - !ruby/object:Gem::Version
69
- version: 0.1.1
129
+ version: 0.1.3
70
130
  type: :runtime
71
131
  prerelease: false
72
132
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,13 +136,14 @@ dependencies:
76
136
  version: '0.1'
77
137
  - - ">="
78
138
  - !ruby/object:Gem::Version
79
- version: 0.1.1
139
+ version: 0.1.3
80
140
  description:
81
141
  email: digital.robertson@gmail.com
82
142
  executables: []
83
143
  extensions: []
84
144
  extra_rdoc_files: []
85
145
  files:
146
+ - data/microblog.txt
86
147
  - lib/noticesys.rb
87
148
  homepage: https://github.com/jrobertson/noticesys
88
149
  licenses:
metadata.gz.sig CHANGED
Binary file