diff --git a/apps/roster/src/roster_db.erl b/apps/roster/src/roster_db.erl index 69ed228d9fb6b450788792b31ee741c884019cec..7c83e403eb5010f063821df802ae0436b6b9a010 100644 --- a/apps/roster/src/roster_db.erl +++ b/apps/roster/src/roster_db.erl @@ -846,36 +846,178 @@ fix_broken_feeds (Opts) -> end, length(ToFix). -%% Add Feature with RosterUUID (AccountId) in settings field for all Contacts +%% Add Feature with RosterUUID (AccountId) in settings field for all Contacts loop_rosters() -> FirstId = mnesia:dirty_first('Roster'), loop_rosters(kvs:get('Roster', FirstId), [], []). - loop_rosters({error, not_found}, Acc, Ers) -> - {lists:flatten(Acc), lists:filter(fun({_, Err}) -> Err =/= [] end, Ers)}; + %{lists:flatten(Acc), lists:filter(fun({_, Err}) -> Err =/= [] end, Ers)}; + lists:flatten(Ers); loop_rosters({ok, #'Roster'{id = Id, userlist = Contacts} = R}, Acc, Ers) -> NextId = mnesia:dirty_next('Roster', Id), {UpdatedContacts, Err} = loop_roster_contacts(Contacts, [], []), - % Uncoment to update Roster - % kvs:put(R#'Roster'{userlist = UpdatedContacts}) - loop_rosters(kvs:get('Roster', NextId), [R#'Roster'{userlist = UpdatedContacts} | Acc], [{R, Err} | Ers]). + % Uncoment to update Roster + % kvs:put(R#'Roster'{userlist = UpdatedContacts}), + loop_rosters(kvs:get('Roster', NextId), [R#'Roster'{userlist = UpdatedContacts} | Acc], [Err | Ers]). loop_roster_contacts([], Acc, Ers) -> {lists:reverse(Acc), lists:reverse(lists:usort(lists:flatten(Ers)))}; loop_roster_contacts([#'Contact'{phone_id = PhoneId, settings = S} = C | Rest], Acc, Ers) -> - {AccountIdFeature, Err} = - case new_feature(PhoneId, account_id) of - [] -> {[], PhoneId}; - Feature -> {Feature, []} - end, - UpdContact = C#'Contact'{settings = lists:flatten(S ++ [AccountIdFeature])}, - loop_roster_contacts(Rest, [UpdContact | Acc], [Err | Ers]). + case lists:keyfind(account_id, #'Feature'.key, S) of + #'Feature'{} -> + loop_roster_contacts(Rest, [C | Acc], Ers); + false -> + {AccountIdFeature, Err} = + case new_feature(PhoneId, account_id) of + [] -> {[], PhoneId}; + Feature -> {Feature, []} + end, + UpdContact = C#'Contact'{settings = lists:flatten(S ++ [AccountIdFeature])}, + loop_roster_contacts(Rest, [UpdContact | Acc], [Err | Ers]) + end. new_feature(PhoneId, account_id) -> - case micro:id_to_uuid('LinkRoster', phone_id, PhoneId) of - [] -> []; - UUID -> #'Feature'{id = uuid:to_string(uuid:uuid4()), - key = account_id, - value = UUID, - group = []} - end. + case micro:id_to_uuid('LinkRoster', phone_id, PhoneId) of + [] -> + LinkRosters = read_link("link_roster.txt"), + case lists:keyfind(PhoneId, #'LinkRoster'.phone_id, LinkRosters) of + #'LinkRoster'{id = UUID} -> io:format("Found: for PhoneId: ~p~n", [PhoneId]), build_feature(UUID); + false -> [] + end; + UUID -> build_feature(UUID) + end. + +build_feature(UUID) -> + #'Feature'{id = list_to_binary(uuid:to_string(uuid:uuid4())), + key = account_id, + value = UUID, + group = []}. + +country_codes() -> + [<<"44-1534">>, <<"44-1624">>, <<"44-1481">>, <<"1-340">>, <<"1-649">>, <<"1-868">>, <<"1-721">>, <<"1-784">>, + <<"1-758">>, <<"1-869">>, <<"1-939">>, <<"1-787">>, <<"1-670">>, <<"1-664">>, <<"1-876">>, <<"1-671">>, + <<"1-473">>, <<"1-849">>, <<"1-829">>, <<"1-809">>, <<"1-767">>, <<"1-345">>, <<"1-284">>, <<"1-441">>, + <<"1-246">>, <<"1-242">>, <<"1-268">>, <<"1-264">>, <<"1-684">>, <<"263">>, <<"260">>, <<"967">>, <<"681">>, + <<"379">>, <<"678">>, <<"998">>, <<"598">>, <<"971">>, <<"380">>, <<"256">>, <<"688">>, <<"993">>, <<"216">>, <<"676">>, + <<"690">>, <<"228">>, <<"255">>, <<"992">>, <<"886">>, <<"963">>, <<"268">>, <<"597">>, <<"249">>, <<"211">>, <<"252">>, + <<"677">>, <<"386">>, <<"421">>, <<"232">>, <<"248">>, <<"381">>, <<"221">>, <<"966">>, <<"239">>, <<"378">>, <<"685">>, + <<"508">>, <<"590">>, <<"290">>, <<"590">>, <<"250">>, <<"262">>, <<"242">>, <<"974">>, <<"351">>, <<"595">>, <<"675">>, + <<"507">>, <<"970">>, <<"680">>, <<"968">>, <<"850">>, <<"683">>, <<"234">>, <<"227">>, <<"505">>, <<"687">>, <<"599">>, + <<"977">>, <<"674">>, <<"264">>, <<"258">>, <<"212">>, <<"382">>, <<"976">>, <<"377">>, <<"373">>, <<"691">>, <<"262">>, + <<"230">>, <<"222">>, <<"692">>, <<"356">>, <<"223">>, <<"960">>, <<"265">>, <<"261">>, <<"389">>, <<"853">>, <<"352">>, + <<"370">>, <<"423">>, <<"218">>, <<"231">>, <<"266">>, <<"961">>, <<"371">>, <<"856">>, <<"996">>, <<"965">>, <<"383">>, + <<"686">>, <<"254">>, <<"962">>, <<"225">>, <<"972">>, <<"353">>, <<"964">>, <<"354">>, <<"852">>, <<"504">>, <<"509">>, + <<"592">>, <<"245">>, <<"224">>, <<"502">>, <<"299">>, <<"350">>, <<"233">>, <<"995">>, <<"220">>, <<"241">>, <<"689">>, + <<"358">>, <<"679">>, <<"298">>, <<"500">>, <<"251">>, <<"372">>, <<"291">>, <<"240">>, <<"503">>, <<"593">>, <<"670">>, + <<"253">>, <<"243">>, <<"420">>, <<"357">>, <<"385">>, <<"506">>, <<"682">>, <<"269">>, <<"235">>, <<"236">>, <<"238">>, + <<"237">>, <<"855">>, <<"257">>, <<"226">>, <<"359">>, <<"673">>, <<"246">>, <<"267">>, <<"387">>, <<"591">>, <<"975">>, + <<"229">>, <<"501">>, <<"375">>, <<"880">>, <<"973">>, <<"994">>, <<"297">>, <<"374">>, <<"672">>, <<"244">>, <<"376">>, + <<"213">>, <<"355">>, <<"84">>, <<"58">>, <<"44">>, <<"90">>, <<"66">>, <<"41">>, <<"46">>, <<"47">>, <<"94">>, + <<"34">>, <<"82">>, <<"27">>, <<"65">>, <<"40">>, <<"48">>, <<"63">>, <<"51">>, <<"92">>, <<"64">>, <<"31">>, + <<"95">>, <<"52">>, <<"60">>, <<"81">>, <<"39">>, <<"98">>, <<"62">>, <<"91">>, <<"36">>, <<"30">>, <<"49">>, <<"33">>, <<"20">>, + <<"45">>, <<"53">>, <<"57">>, <<"86">>, <<"56">>, <<"55">>, <<"32">>, <<"43">>, <<"61">>, <<"54">>, <<"93">>, <<"1">>, <<"7">>]. + +correct_numbers(PhoneIds) -> + correct_numbers([roster:phone(Pid) || Pid <- PhoneIds], []). + +correct_numbers([], Acc) -> + Acc; +correct_numbers([Number | Rest], Acc) -> + case lists:filter(fun(Code) -> + case string:split(Number, Code) of + [Number] -> false; + [<<>>, <<"0", GoodNumber/binary>>] -> true; + [<<>>, GoodNumber] -> true; + _ -> false + end + end, country_codes()) of + [CountryCode] -> + NewNumber = + case string:replace(Number, CountryCode, <<"">>, leading) of + [<<>>, <<>>, <<"0", FixedNumber/binary>>] -> FixedNumber; + [<<>>, <<>>, Num] -> Num; + Err -> {error, Err} + end, + case libphonenumbers:is_mobile_valid_phone(<<"+", CountryCode/binary, NewNumber/binary>>) of + true -> correct_numbers(Rest, [<> | Acc]); + false -> io:format("Invalid2: ~p | Code: ~p NewNumber: ~p~n", [Number, CountryCode, NewNumber]), correct_numbers(Rest, Acc) + end; + Err -> + io:format("Invalid1: ~p Err: ~p~n", [Number, Err]), correct_numbers(Rest, Acc) + end. + +get_all_phones([], Phones) -> + Phones; +get_all_phones([Id | Rest], Acc) -> + case catch uuid:is_valid(binary_to_list(Id)) of + true -> get_all_phones(Rest, Acc); + _ -> get_all_phones(Rest, [Id | Acc]) + end. + +get_all_phone_ids([], PhoneIds) -> + PhoneIds; +get_all_phone_ids([Rid | Rest], Acc) -> + get_all_phone_ids(Rest, [roster:phone_id(Rid) | Acc]). + + +has_uuid_profile([], Acc) -> + lists:flatten(Acc); +has_uuid_profile([Phone | Rest], Acc) -> + Phone1 = case kvs:index('LinkProfile', phone, Phone) of + [] -> io:format("Not Found: ~p~n", [Phone]), Phone; + _ -> [] + end, + has_uuid_profile(Rest, [Phone1 | Acc]). + +has_uuid_roster([], Acc) -> + lists:flatten(Acc); +has_uuid_roster([PhoneId | Rest], Acc) -> + PhoneId1 = case kvs:index('LinkRoster', phone_id, PhoneId) of + [] -> io:format("Not Found: ~p~n", [PhoneId]), PhoneId; + _ -> [] + end, + has_uuid_roster(Rest, [PhoneId1 | Acc]). + +all_contacts([], Acc) -> + Contacts = lists:usort(lists:flatten(Acc)), + lists:usort([PhoneId || #'Contact'{phone_id = PhoneId} <- Contacts]); +all_contacts([Rid | Rest], Acc) -> + {ok, #'Roster'{userlist = Contacts}} = kvs:get('Roster', Rid), + Filtered = lists:filter(fun(#'Contact'{phone_id = Pid}) -> Pid =/= roster:phone_id(Rid) end, Contacts), + all_contacts(Rest, [Filtered | Acc]). + +add_linkage([], Acc1, Acc2) -> + io:format("Acc1: ~p~nAcc2: ~p~n", [Acc1, Acc2]); +add_linkage([{PhoneMiss, PhoneHas} | Rest], Acc1, Acc2) -> + case kvs:index('LinkProfile', phone, PhoneHas) of + [#'LinkProfile'{id = P_UUID}] -> + LinkP = #'LinkProfile'{id = P_UUID, phone = PhoneMiss}, + {ok, #'Profile'{rosters = [RidMiss]}} = kvs:get('Profile', PhoneMiss), + {ok, #'Profile'{rosters = [RidHas]}} = kvs:get('Profile', PhoneHas), + case kvs:index('LinkRoster', phone_id, roster:phone_id(RidHas)) of + [#'LinkRoster'{id = R_UUID}] -> + LinkR = #'LinkRoster'{id = R_UUID, phone_id = roster:phone_id(RidMiss)}, + {struct, Json1} = json_rec:to_json(LinkP, roster_export), + {struct, Json2} = json_rec:to_json(LinkR, roster_export), + add_linkage(Rest, + [jsx:encode(Json1) | Acc1], + [jsx:encode(Json2) | Acc2]); + [] -> + io:format("Error LinkRoster ~p~n", [PhoneHas]) + end; + [] -> + io:format("ERROR Link Proile: ~p~n Acc: ~p~n", [PhoneHas, PhoneMiss]) + end. + +read_link(FileName) -> + {ok, Text} = file:read_file("/home/nynja/depot/server/" ++ FileName), + read_link(string:split(Text, ";", all), []). +read_link([], Acc) -> + Acc; +read_link([Link | Rest], Acc) -> + case jsx:decode(Link) of + [{<<"phone">>, Phone}, {<<"id">>, UUID}] -> + read_link(Rest, [#'LinkProfile'{id = UUID, phone = Phone} | Acc]); + [{<<"phone_id">>, PhoneId}, {<<"id">>, UUID}] -> + read_link(Rest, [#'LinkRoster'{id = UUID, phone_id = PhoneId} | Acc]) + end.