Index: api/lp/tweet.t ================================================================== --- api/lp/tweet.t +++ api/lp/tweet.t @@ -14,33 +14,35 @@ local wrap = lib.tpl.mk [[{ "\@context": "https://@+domain/s/litepub.jsonld", "type": "@kind", "actor": "https://@+domain/user/@^uid", - "published": "@$pubtime", + "published": "@pubtime", "id": "https://@+domain/api/lp/act/@^aid", "object": @obj }]] local terra lp_tweet(co: &lib.srv.convo, p: &lib.store.post, act_wrap: bool) - + var opdate = lib.conv.datetime(&co.srv.pool, p.posted) + var tweet = (obj { domain = co.srv.cfg.domain, uid = p.author, pid = p.id; html = lib.smackdown.html(&co.srv.pool, p.body, false); - raw = p.body, pubtime = '', extra = ''; + raw = p.body, pubtime = opdate, extra = ''; }):poolstr(&co.srv.pool) if act_wrap then return (wrap { - domain = co.srv.cfg.domain; + domain = co.srv.cfg.domain, obj = tweet; kind = lib.trn(p.rtdby == 0, 'Create', 'Announce'); uid = lib.trn(p.rtdby == 0, p.author, p.rtdby); aid = lib.trn(p.rtdby == 0, p.id, p.rtact); - pubtime = '', obj = tweet; + pubtime = lib.trn(p.rtdby == 0, opdate, + lib.conv.datetime(&co.srv.pool,p.rtdat)); }):poolstr(&co.srv.pool) else return tweet end end return lp_tweet Index: backend/pgsql.t ================================================================== --- backend/pgsql.t +++ backend/pgsql.t @@ -1073,14 +1073,15 @@ then p.ptr.chgcount = 0 else p.ptr.chgcount = r:int(uint32,row,11) end p.ptr.accent = r:int(int16,row,12) p.ptr.rtdby = r:int(uint64,row,13) - p.ptr.rtact = r:int(uint64,row,14) - p.ptr.likes = r:int(uint32,row,15) - p.ptr.rts = r:int(uint32,row,16) - p.ptr.isreply = r:bool(row,17) + p.ptr.rtdat = r:int(uint64,row,14) + p.ptr.rtact = r:int(uint64,row,15) + p.ptr.likes = r:int(uint32,row,16) + p.ptr.rts = r:int(uint32,row,17) + p.ptr.isreply = r:bool(row,18) p.ptr.localpost = r:bool(row,0) return p end local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor) Index: backend/schema/pgsql-views.sql ================================================================== --- backend/schema/pgsql-views.sql +++ backend/schema/pgsql-views.sql @@ -111,26 +111,27 @@ convoheaduri text, chgcount integer, -- ephemeral accent smallint, rtdby bigint, -- note that these must be 0 if the record - rtid bigint, -- in question does not represent an RT! + rtdat bigint, -- in question does not represent an RT! + rtid bigint, -- (this one too) n_likes integer, n_rts integer, isreply bool -- true if parent in (table posts); saves us a bunch of queries ); create or replace function -pg_temp.parsavpg_translate_post(parsav_posts,bigint,bigint) +pg_temp.parsavpg_translate_post(parsav_posts,bigint,bigint,bigint) returns pg_temp.parsavpg_intern_post as $$ select a.origin is null, ($1).id, ($1).author, ($1).subject,($1).acl, ($1).body, ($1).posted, ($1).discovered, ($1).edited, ($1).parent, ($1).convoheaduri,($1).chgcount, coalesce(c.value, -1)::smallint, - $2 as rtdby, $3 as rtid, + $2 as rtdby, $3 as rtdat, $4 as rtid, re.likes, re.rts, ($1).parent in (select id from parsav_posts) from parsav_actors as a left join parsav_actor_conf_ints as c on c.key = 'ui-accent' and @@ -160,11 +161,13 @@ ), content as (select * from posts union select * from rts) select pg_temp.parsavpg_translate_post(cn.orig, - coalesce(cn.promoter,0), coalesce(cn.promotion,0) + coalesce(cn.promoter,0), + coalesce(cn.promotime,0), + coalesce(cn.promotion,0) ) as post, cn.promotime::bigint as tltime, coalesce(cn.promoter, (cn.orig).author) as promoter from content as cn order by cn.promotime desc ADDED conv.t Index: conv.t ================================================================== --- conv.t +++ conv.t @@ -0,0 +1,26 @@ +-- vim: ft=terra +local m={} +local pstr = lib.str.t + +terra m.datetime(pool: &lib.mem.pool, when: lib.osclock.time_t) + -- formats a unix epoch time as a dumbfuck XSD datetime spec + var td: lib.osclock.tm + if lib.osclock.gmtime_r(&when, &td) == nil then + return pstr.null() + end + + var tpl = [lib.tpl.mk ('@#year:-@MM@#month:-@dd@#day:T'.. + '@hh@#hour::@mm@#min::@ss@#sec:Z')] { + year = td.tm_year + 1900, month = td.tm_mon + 1, day = td.tm_mday; + hour = td.tm_hour, min = td.tm_min, sec = td.tm_sec; + MM = lib.trn(td.tm_mon+1 < 10, '0', ''); + dd = lib.trn(td.tm_mday < 10, '0', ''); + ss = lib.trn(td.tm_sec < 10, '0', ''); + mm = lib.trn(td.tm_min < 10, '0', ''); + hh = lib.trn(td.tm_min < 10, '0', ''); + } + + return tpl:poolstr(pool) +end + +return m Index: parsav.t ================================================================== --- parsav.t +++ parsav.t @@ -443,10 +443,11 @@ lib.load { 'mem', 'math', 'str', 'file', 'crypt', 'ipc'; 'http', 'html', 'session', 'tpl', 'store', 'acl'; 'smackdown'; -- md-alike parser + 'conv'; -- miscellaneous conversion/munging functions } local be = {} for _, b in pairs(config.backends) do be[#be+1] = terralib.loadfile(string.format('backend/%s.t',b))() Index: store.t ================================================================== --- store.t +++ store.t @@ -233,10 +233,11 @@ localpost: bool accent: int16 rts: uint32 likes: uint32 rtdby: uint64 -- 0 if not rt + rtdat: m.timepoint -- 0 if not rt, time of promotion otherwise rtact: uint64 -- 0 if not rt, id of rt action otherwise isreply: bool source: &m.source -- save :: bool -> {} (defined in acl.t due to dep. hell) Index: tpl.t ================================================================== --- tpl.t +++ tpl.t @@ -36,11 +36,11 @@ str = str:gsub(' ?', file) end) - for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([+:!$#%^]?)([-a-zA-Z0-9_]+)()') do + for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([+:!$#%^]?)([-a-zA-Z0-9_]+):?()') do if string.sub(str,start-1,start-1) ~= '\\' then segs[#segs+1] = string.sub(str,last,start-1) fields[#segs] = { key = key:gsub('-','_'), mode = (mode ~= '' and mode or nil) } last = stop end