parsav  Check-in [a4b4af5ca4]

Overview
Comment:begin work on circles
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a4b4af5ca4157d4716100e593c53b6427f46222b2a9d48f4c4c791c6774b767d
User & Date: lexi on 2021-01-13 15:01:13
Other Links: manifest | tags
Context
2021-01-14
01:11
more work on UI and circles check-in: 03ea3dffe7 user: lexi tags: trunk
2021-01-13
15:01
begin work on circles check-in: a4b4af5ca4 user: lexi tags: trunk
13:57
implement some sanctions check-in: 60040f3ca3 user: lexi tags: trunk
Changes

Modified backend/pgsql.t from [bd352a7166] to [96ec125a09].

   282    282   
   283    283   	actor_notice_enum = {
   284    284   		params = {uint64}, sql = [[
   285    285   			select (notice).* from pg_temp.parsavpg_notices
   286    286   			where rcpt = $1::bigint
   287    287   		]];
   288    288   	};
          289  +
          290  +	circle_search = {
          291  +		params = {uint64,uint64}, sql = [[
          292  +			select name, id, owner, array_length(members,1) from parsav_circles where
          293  +				($1::bigint = 0 or $1::bigint = owner) and
          294  +				($2::bigint = 0 or $2::bigint = id)
          295  +		]];
          296  +	};
          297  +
          298  +	circle_members_fetch_cid = {
          299  +		params = {uint64, uint64}, sql = [[
          300  +			select unnest(members) from parsav_circles where
          301  +				($1::bigint = 0 or owner = $1::bigint) and
          302  +				id = $2::bigint
          303  +		]];
          304  +	};
          305  +
          306  +	circle_members_fetch_name = {
          307  +		params = {uint64, pstring}, sql = [[
          308  +			select unnest(members) from parsav_circles where
          309  +				($1::bigint = 0 or owner = $1::bigint) and
          310  +				name = $2::text
          311  +		]];
          312  +	};
   289    313   
   290    314   	auth_sigtime_user_fetch = {
   291    315   		params = {uint64}, sql = [[
   292    316   			select authtime::bigint
   293    317   			from parsav_actors where id = $1::bigint
   294    318   		]];
   295    319   	};
................................................................................
  2035   2059   			end
  2036   2060   			return 0, false
  2037   2061   		end];
  2038   2062   	actor_conf_int_set = [terra(src: &lib.store.source, uid: uint64, key: rawstring, value: uint64): {}
  2039   2063   			queries.actor_conf_int_set.exec(src,uid,key,value) end];
  2040   2064   	actor_conf_int_reset = [terra(src: &lib.store.source, uid: uint64, key: rawstring): {}
  2041   2065   			queries.actor_conf_int_reset.exec(src,uid,key) end];
         2066  +	
         2067  +	circle_search = [terra(
         2068  +		src: &lib.store.source,
         2069  +		pool:&lib.mem.pool,
         2070  +		uid: uint64,
         2071  +		cid: uint64
         2072  +	): lib.mem.ptr(lib.store.circle)
         2073  +		var res = queries.circle_search.exec(src, uid, cid)
         2074  +		if res.sz == 0 then return [lib.mem.ptr(lib.store.circle)].null() end
         2075  +		defer res:free()
         2076  +
         2077  +		var rt = pool:alloc(lib.store.circle, res.sz)
         2078  +		for i = 0, res.sz do
         2079  +			var name = res:_string(i,0)
         2080  +			rt(i) = lib.store.circle {
         2081  +				name = name:pdup(pool);
         2082  +				cid = res:int(uint64,i,1);
         2083  +				owner = res:int(uint64,i,2);
         2084  +				memcount = res:int(uint64,i,3);
         2085  +			}
         2086  +		end
         2087  +
         2088  +		return rt
         2089  +	end];
         2090  +
         2091  +	circle_members_fetch_cid = [terra(
         2092  +		src: &lib.store.source,
         2093  +		pool:&lib.mem.pool,
         2094  +		uid: uint64,
         2095  +		cid: uint64
         2096  +	): lib.mem.ptr(uint64)
         2097  +		var res = queries.circle_members_fetch_cid.exec(src,uid,cid)
         2098  +		if res.sz == 0 then return [lib.mem.ptr(uint64)].null() end
         2099  +		defer res:free()
         2100  +
         2101  +		var rt = pool:alloc(uint64, res.sz)
         2102  +		for i = 0, res.sz do rt(i) = res:int(uint64,i,0) end
         2103  +
         2104  +		return rt
         2105  +	end];
  2042   2106   
  2043   2107   	actor_auth_register_uid = nil; -- TODO better support non-view based auth
  2044   2108   }
  2045   2109   
  2046   2110   return b

Modified mem.t from [05a21ff4d9] to [a251bec86e].

   105    105   		self.ptr = self.ptr + n
   106    106   		self.ct = self.ct - n
   107    107   		return self.ptr
   108    108   	end
   109    109   	terra t.methods.null(): t return t { ptr = nil, ct = 0 } end -- maybe should be a macro?
   110    110   	terra t:ref() return self.ptr ~= nil end
   111    111   	t.metamethods.__not = macro(function(self) return `not self:ref() end)
   112         -	t.metamethods.__apply = macro(function(self,idx) return `self.ptr[idx] end)
          112  +	t.metamethods.__apply = macro(function(self,idx) return `self.ptr[ [idx or 0] ] end)
          113  +	t.metamethods.__update = macro(function(self,idx,rhs)
          114  +		return quote self.ptr[idx] = rhs end end)
          115  +
   113    116   	if not ty:isstruct() then
   114    117   		terra t:cmp_raw(other: &ty)
   115    118   			for i=0, self.ct do
   116    119   				if self.ptr[i] ~= other[i] then return false end
   117    120   			end
   118    121   			return true
   119    122   		end

Modified render/timeline.t from [dac341c838] to [900216dd8b].

     5      5   requires_login(m: modes.t): bool
     6      6   	return m == modes.follow
     7      7   	    or m == modes.mutual
     8      8   	    or m == modes.circle
     9      9   end
    10     10   
    11     11   local terra 
    12         -render_timeline(co: &lib.srv.convo, modestr: lib.mem.ref(int8))
           12  +render_timeline(co: &lib.srv.convo, hpath: lib.mem.ptr(lib.mem.ref(int8)))
           13  +	var modestr = lib.str.ref.null()
           14  +	var spec    = lib.str.ref.null()
           15  +	if hpath.ct >= 2 then
           16  +		modestr = hpath(1)
           17  +		if hpath.ct >= 3 then spec = hpath(2) end
           18  +	end
    13     19   	var mode = modes.follow
    14     20   	var circle: uint64 = 0
    15         -	if     modestr:cmp('local') then mode = [modes['local']]
    16         -	elseif modestr:cmp('mutual') then mode = modes.mutual
    17         -	elseif modestr:cmp('fedi') then mode = modes.fedi
    18         -	elseif modestr:cmp('circle') then mode = modes.circle
           21  +	if modestr:ref() then
           22  +		if     modestr:cmp('local' ) then mode = [modes['local']]
           23  +		elseif modestr:cmp('mutual') then mode = modes.mutual
           24  +		elseif modestr:cmp('fedi'  ) then mode = modes.fedi
           25  +		elseif modestr:cmp('circle') then mode = modes.circle
           26  +		end
    19     27   	end
    20     28   	if requires_login(mode) and co.aid == 0 then mode = [modes['local']] end
    21     29   
    22     30   
    23     31   	var stoptime = lib.osclock.time(nil)
    24     32   
    25     33   	var posts = [lib.mem.vec(lib.mem.ptr(lib.store.post))] { 
................................................................................
    41     49   	var acc = co:stra(1024)
    42     50   	var modelabels = arrayof(pstr, 'followed', 'mutuals', 'local instance', 'fediverse', 'circle')
    43     51   	var modelinks = arrayof(pstr, [modes.members])
    44     52   	acc:lpush('<div style="text-align: right"><em>showing ')
    45     53   	for i=0, [modelabels.type.N] do
    46     54   		if co.aid ~= 0 or not requires_login(i) then
    47     55   			if i > 0 then acc:lpush(' ยท ') end
    48         -			if i == mode then
           56  +			if i == mode and not (mode == modes.circle and spec:ref()) then
    49     57   				acc:lpush('<strong>'):ppush(modelabels[i]):lpush('</strong>')
    50     58   			else
    51     59   				acc:lpush('<a href="/tl/'):ppush(modelinks[i]):lpush('">'):ppush(modelabels[i]):lpush('</a>')
    52     60   			end
    53     61   		end
    54     62   	end
    55     63   	acc:lpush('</em></div>')
    56         -	acc:lpush('<div id="tl" data-live="10">')
    57     64   	var newest: lib.store.timepoint = 0
    58         -	for i = 0, posts.sz do
    59         -		var author = co:uid2actor(posts(i).ptr.author)
    60         -		if mode == modes.mutual and posts(i).ptr.author ~= co.who.id then
    61         -			if not author.relationship.recip.follow() then goto skip end
           65  +	if mode == modes.circle and not spec then
           66  +		var circles = co.srv:circle_search(&co.srv.pool, co.who.id, 0)
           67  +		acc:lpush '<menu class="circles">'
           68  +		for i:intptr = 0, circles.ct do
           69  +			acc:lpush '<li><a href="/tl/circle/'
           70  +			   :shpush(circles(i).cid)
           71  +			   :lpush '">'
           72  +			   :ppush(circles(i).name)
           73  +			   :lpush '</a></li>'
           74  +		end
           75  +		-- TODO list circles
           76  +		acc:lpush '</menu>'
           77  +	else
           78  +		acc:lpush('<div id="tl" data-live="10">')
           79  +		for i = 0, posts.sz do
           80  +			var author = co:uid2actor(posts(i).ptr.author)
           81  +			if mode == modes.mutual and posts(i).ptr.author ~= co.who.id then
           82  +				if not author.relationship.recip.follow() then goto skip end
           83  +			end
           84  +			if author.relationship.rel.mute() or 
           85  +			   author.relationship.rel.avoid() or 
           86  +			   author.relationship.recip.exclude() then goto skip end
           87  +			lib.render.tweet(co, posts(i).ptr, &acc)
           88  +			var t = lib.math.biggest(lib.math.biggest(posts(i).ptr.posted, posts(i).ptr.discovered),posts(i).ptr.edited)
           89  +			if t > newest then newest = t end
           90  +			::skip:: posts(i):free()
    62     91   		end
    63         -		if author.relationship.rel.mute() or 
    64         -		   author.relationship.rel.avoid() or 
    65         -		   author.relationship.recip.exclude() then goto skip end
    66         -		lib.render.tweet(co, posts(i).ptr, &acc)
    67         -		var t = lib.math.biggest(lib.math.biggest(posts(i).ptr.posted, posts(i).ptr.discovered),posts(i).ptr.edited)
    68         -		if t > newest then newest = t end
    69         -		::skip:: posts(i):free()
           92  +		if posts.run > 0 then posts:free() end
           93  +		acc:lpush('</div>')
    70     94   	end
    71         -	if posts.run > 0 then posts:free() end
    72         -	acc:lpush('</div>')
    73     95   
    74     96   	var doc = [lib.srv.convo.page] {
    75     97   		title = 'timeline';
    76     98   		body = acc:finalize();
    77     99   		class = 'timeline';
    78    100   		cache = false;
    79    101   	}
    80         -	co:livepage(doc,newest)
          102  +	if newest ~= 0
          103  +		then co:livepage(doc,newest)
          104  +		else co:stdpage(doc)
          105  +	end
    81    106   	--doc.body:free()
    82    107   end
    83    108   return render_timeline

Modified route.t from [cc19a11396] to [bb5bfba2ee].

   218    218   		var idlen = lib.math.shorthand.gen(newid, idbuf)
   219    219   		var redirto: lib.str.acc redirto:compose('/post/',{idbuf,idlen}) defer redirto:free()
   220    220   		co:reroute(redirto.buf)
   221    221   	end
   222    222   end
   223    223   
   224    224   terra http.timeline(co: &lib.srv.convo, mode: hpath)
   225         -	lib.render.timeline(co,lib.trn(mode.ptr == nil, rstring{ptr=nil}, mode.ptr[1]))
          225  +	lib.render.timeline(co,mode)
   226    226   end
   227    227   
   228    228   terra http.documentation(co: &lib.srv.convo, path: hpath)
   229    229   	if path.ct == 2 then
   230    230   		lib.render.docpage(co,path(1))
   231    231   	elseif path.ct == 1 then
   232    232   		lib.render.docpage(co, rstring.null())

Modified store.t from [303dfd42c8] to [8e00371af1].

   236    236   	rtdby: uint64 -- 0 if not rt
   237    237   	rtact: uint64 -- 0 if not rt, id of rt action otherwise
   238    238   	isreply: bool
   239    239   	source: &m.source
   240    240   
   241    241   	-- save :: bool -> {} (defined in acl.t due to dep. hell)
   242    242   }
          243  +
          244  +struct m.circle {
          245  +	cid: uint64
          246  +	owner: uint64
          247  +	name: lib.str.t
          248  +-- ephemera
          249  +	memcount: intptr
          250  +}
   243    251   
   244    252   struct m.artifact {
   245    253   	rid: uint64
   246    254   	owner: uint64
   247    255   	desc: str
   248    256   	folder: str
   249    257   	mime: str
................................................................................
   461    469   			-- undo: bool
   462    470   	post_react: {&m.source, uint64, uint64, pstring} -> {}
   463    471   			-- emoji: pstring (null to delete previous reaction, otherwise adds/changes)
   464    472   	post_act_cancel: {&m.source, uint64} -> {}
   465    473   	post_liked_uid: {&m.source, uint64, uint64} -> bool
   466    474   	post_reacted_uid: {&m.source, uint64, uint64} -> bool
   467    475   	post_act_fetch_notice: {&m.source, uint64} -> m.notice
          476  +
          477  +	circle_search:  {&m.source, &lib.mem.pool, uint64, uint64} -> lib.mem.ptr(m.circle)
          478  +	circle_create: {&m.source, uint64, pstring} -> {}
          479  +	circle_destroy: {&m.source, uint64, uint64} -> {}
          480  +	circle_members_fetch_cid:  {&m.source, &lib.mem.pool, uint64, uint64} -> lib.mem.ptr(uint64)
          481  +	circle_members_fetch_name: {&m.source, &lib.mem.pool, uint64, pstring} -> lib.mem.ptr(uint64)
          482  +	circle_members_add_uid: {&m.source, uint64, uint64} -> {}
          483  +	circle_members_del_uid: {&m.source, uint64, uint64} -> {}
   468    484   
   469    485   	thread_latest_arrival_calc: {&m.source, uint64} -> m.timepoint
   470    486   
   471    487   	artifact_instantiate: {&m.source, lib.mem.ptr(uint8), lib.mem.ptr(int8)} -> uint64
   472    488   		-- instantiate an artifact in the database, either installing a new
   473    489   		-- artifact or returning the id of an existing artifact with the same hash
   474    490   			-- artifact: bytea

Modified str.t from [ee5af81e76] to [0c9ba1d780].

    28     28   	      (@str == @' ' or @str == @'\t' or @str == @'\n') do
    29     29   		str = str + 1
    30     30   		maxlen = maxlen - 1
    31     31   	end
    32     32   	return str
    33     33   end
    34     34   
    35         -
    36     35   do local strptr = (lib.mem.ptr(int8))
    37     36   	local strref = (lib.mem.ref(int8))
    38     37   	local byteptr = (lib.mem.ptr(uint8))
    39     38   	local function install_funcs(ty)
    40     39   		ty.metamethods.__cast = function(from,to,e)
    41     40   			local v = e:asvalue()
    42     41   			if type(v) == 'string' then
    43     42   				return `ty {ptr = v, ct = [#v]}
    44     43   			elseif from == &int8 then
    45     44   				return `ty {ptr = e, ct = m.sz(e)}
    46     45   			elseif to == &int8 then
    47     46   				return e.ptr
    48     47   			end
           48  +		end
           49  +		terra ty:pdup(p: &lib.mem.pool): strptr
           50  +			if not @self then return strptr.null() end
           51  +			if self.ct == 0 then self.ct = m.sz(self.ptr) end
           52  +			var newstr = p:alloc(int8, self.ct)
           53  +			lib.mem.cpy(newstr.ptr, self.ptr, self.ct)
           54  +			return newstr
    49     55   		end
    50     56   		terra ty:cmp(other: ty)
    51     57   			if self.ptr == nil and other.ptr == nil then return true end
    52     58   			if self.ptr == nil or other.ptr == nil then return false end
    53     59   
    54     60   			var sz = lib.math.biggest(self.ct, other.ct)
    55     61   			for i = 0, sz do