also fixes sending out posts to open connections
EDLKGFB5NWTZTHEO6IAR5M4W4533KJI4O6673MKJNTW3JPHQZP5AC 2R3WFEOT3WWS6NFBBABSVRUNUPTXHFFMGPZZQOCPLTD2WB3U55HQC JMYRP5MUPSBHABHBPIO45F6RC7QSQSNO2EJDUDUIQXX3MEEFDOAQC J32TNYTRQJ3YTGFSI5FXW63R5ACT5SZQ6C4YSHLAZ4HXYAHAN7YQC JVURIEXR72OUGZ2EHP5HB6OMXUNPHMAV66YUUP2444TPOG5XGASQC 55WLMLEEVBRSTAFRZ5RGF7TOGUF5OPVCPA2TMHAQK45OUO7PA3YQC IHBNW3GI2XB6KAWUYRLL6KDOBUNUOU3N7RRLS6BFNW6SE7ZDHLWQC BSISJB2O2HKYGSCX6HIIMLBIXCZ66BRCZH3622G2NOQJRJ5S3HLAC CBHKQGLDCAH2E4ZNACITBSMADOKPERFCWQPUGMH7UN5TLJXLYI4QC ST7Y5WTYIQNKUOVXW6T5PQZL6R3VUYC37BAEQOA2FL6AYVPR4OLAC MONVI5STEDKY5ALVMEXJJXDUX6XQRKTFLP7BBNOQML3VSJEM2JAAC QHK3BXHEC6IAAI7HK76Y7W3IQQIEFH7TD7AYMBCLOE7U2L7BT2LQC RZB6HZ2NI5PIUIWQL63CSKXZGGUG4L6XCSCGR3TI723OO57NDT3AC %?assert(false),
{ok, PubAlfi} = peer:node_public_key(Alfi),{ok, PubBert} = peer:node_public_key(Bert),NickAlfi = "Alfi",NickBert = "Not ernie!!",ok = peer:set_nick(Alfi, NickAlfi),ok = peer:set_nick(Bert, NickBert),C = "test",peer:join(Alfi, C),peer:join(Bert, C),T1 = "someone here?",T2 = "is this thing on?",ok = peer:write(Alfi, C, T1),timer:sleep(500), %% enforce orderingok = peer:write(Bert, C, T2),{ok, PeerAddr} = peer:node_addr(Bert),ok = peer:dial(Alfi, PeerAddr),timer:sleep(1000),Check = fun(Peer) ->{ok, {Texts, Users}} = peer:read(Peer, C),[{UserIdAlfi, _, T1}, {UserIdBert, _, T2}] = Texts,{AlfiInfo, UsersSansAlfi} = maps:take(UserIdAlfi, Users),?assertEqual({NickAlfi, PubAlfi}, AlfiInfo),{BertInfo, #{}} = maps:take(UserIdBert, UsersSansAlfi),?assertEqual({NickBert, PubBert}, BertInfo)end,lists:foreach(Check, [Alfi, Bert]),%% that's nice but do we also transmit posts while connected?ok = peer:write(Alfi, C, "ohai! o/"),timer:sleep(500),{ok, {Texts, _}} = peer:read(Bert, C),?assertEqual(3, length(Texts)),ok = peer:write(Bert, C, "nice to meet you!"),timer:sleep(250),{ok, {Texts2, _}} = peer:read(Alfi, C),?assertEqual(4, length(Texts2)),
-export([channels_joined/1, channels_known/1, channel_state/2, join/2, leave/2]).-export([set_topic/3, set_nick/2, write/3]).
-export([channels_joined/1, channels_known/1, channel_members/2, join/2, leave/2]).-export([set_topic/3, set_nick/2, read/2, write/3]).
SentPeers = lists:foldl(fun({Direction, ReqId, Peer}, AccPeers) ->case Direction ofreceived ->{Peer, [Header, _]} = maps:get(ReqId, ActiveIn),case proplists:get_value(type, Header) of4 ->{ok, {_, _, Size}} = send_hash_response(Peer, ReqId, [PostHash]),update_peer_sent(AccPeers, Peer, Size);_ -> AccPeers % ignoredend;sent ->AccPeersendend, Peers, maps:get(Chan, Chans)),
%% find incoming channel time range (type:4) requests which want this postF = fun({Direction, ReqId, Peer}, AccPeers) ->case Direction ofreceived ->{Peer, [Header, _]} = maps:get(ReqId, ActiveIn),case proplists:get_value(msgType, Header) of4 ->{ok, {_, _, Size}}= send_hash_response(Peer, ReqId, [PostHash]),update_peer_sent(AccPeers, Peer, Size);_ -> AccPeersend;sent -> AccPeersendend,SentPeers = lists:foldl(F, Peers, maps:get(Chan, Chans)),io:format("[Wrote] #~p: ~p~n", [Chan, Text]),
io:format("[DEBUG] Received incoming state req for ~p from ~p~n",[RequestedChan, Peer]),{ok, Hashes} = db:get_channel_heads(Db, RequestedChan),
%% io:format("[DEBUG] Received incoming state req for ~p from ~p~n",%% [RequestedChan, Peer]),{ok, Hashes} = db:get_channel_state(Db, RequestedChan),
-export([has_post/2, get_text_hashes_by_time_range/5]).-export([channels_join/2, channels_leave/2, channels_list/1, get_channel_heads/2, get_channel_state/2]).
-export([has_post/2, get_text_hashes_by_time_range/5, get_texts_for_channel/2]).-export([channels_join/2, channels_leave/2, channels_list/1]).-export([get_channel_state/2, get_channel_members/2, get_channel_heads/2]).
handle_call({textsForChannel, Chan}, _From, [{sql, Db}, _] = State) ->Qry = "SELECT user_id, timestamp, text from posts where channel = ? and type = 0 order by timestamp asc",QryChan = {blob, list_to_binary(Chan)},[{columns, ["user_id", "timestamp", "text"]}, {rows, Rows}] = sqlite3:sql_exec(Db, Qry, [QryChan]), %%, Start, End, Limit]),%% map rows and add user informationQryUser = "SELECT name, public_key FROM users where id = ?",F = fun({UserId, Ts, {blob, TextBin}}, {Texts, Users}) ->NewUsers = case maps:is_key(UserId, Users) oftrue -> Users;false ->[{columns, ["name", "public_key"]},{rows, [{NameBin, {blob, PubKey}}]}] = sqlite3:sql_exec(Db, QryUser, [UserId]),Name = unicode:characters_to_list(NameBin),Users#{UserId => {Name, PubKey}}end,Text = unicode:characters_to_list(TextBin),{Texts ++ [{UserId, Ts, Text}], NewUsers}end,Result = lists:foldl(F, {[], #{}}, Rows),{reply, {ok, Result}, State};
Qry = "SELECT hash, user_id from posts where channel = ? and type > 1 order by timestamp desc",
Qry = "SELECT DISTINCT source FROM links "++ "WHERE source NOT IN ("++ " SELECT DISTINCT parent FROM links"++ " WHERE channel = ? or channel is null)",QryChan = case Chan ofnull -> null;_ when is_list(Chan) -> {blob, list_to_binary(Chan)}end,[{columns, ["source"]}, {rows, Rows}] = sqlite3:sql_exec(Db, Qry, [QryChan]),Result = [Hash || {{blob, Hash}} <- Rows],{reply, {ok, Result}, State};handle_call({channelsState, Chan}, _, [{sql, Db}, _] = State) ->Qry = "SELECT hash, user_id from posts where channel = ? and type > 2 order by timestamp",
MembersQry = "SELECT users.name as name, users.public_key as pub_key, posts.timestamp as timestamp "++ "FROM channel_members "++ "JOIN posts ON channel_members.post_hash = posts.hash "++ "JOIN users ON channel_members.user_id = users.id "++ "WHERE channel_members.channel = ?",
MembersQry = "SELECT u.name as name, u.public_key as pub_key, p.timestamp as timestamp, p.type as type "++ "FROM channel_members m "++ "JOIN posts p ON m.last_hash = p.hash "++ "JOIN users u ON m.user_id = u.id "++ "WHERE m.channel = ?",
Res = sqlite3:write(Db, channel_members, [ {channel, Chan}, {user_id, UserId}, {post_hash, {blob, Hash}}]),
Qry = "INSERT INTO channel_members(channel, user_id, last_hash) VALUES (?, ?, ?) "++ "ON CONFLICT(user_id) DO UPDATE SET last_hash=excluded.last_hash",Res = sqlite3:sql_exec(Db, Qry, [ Chan, UserId, {blob, Hash}]),
Qry = "DELETE FROM channel_members where channel = ? and user_id = ?",ok = sqlite3:sql_exec(Db, Qry, [Chan, UserId]),
Qry = "UPDATE channel_members set last_hash = ? where channel = ? and user_id = ?",ok = sqlite3:sql_exec(Db, Qry, [{blob, Hash}, Chan, UserId]),