1package eu.siacs.conversations.services;
2
3import android.support.annotation.NonNull;
4import android.util.Log;
5
6import com.google.common.cache.Cache;
7import com.google.common.cache.CacheBuilder;
8
9import java.io.IOException;
10import java.util.Collections;
11import java.util.List;
12import java.util.concurrent.Executors;
13import java.util.concurrent.TimeUnit;
14
15import eu.siacs.conversations.Config;
16import eu.siacs.conversations.http.HttpConnectionManager;
17import eu.siacs.conversations.http.services.MuclumbusService;
18import okhttp3.OkHttpClient;
19import retrofit2.Call;
20import retrofit2.Callback;
21import retrofit2.Response;
22import retrofit2.Retrofit;
23import retrofit2.converter.gson.GsonConverterFactory;
24
25public class ChannelDiscoveryService {
26
27 private final XmppConnectionService service;
28
29
30 private MuclumbusService muclumbusService;
31
32 private final Cache<String, List<MuclumbusService.Room>> cache;
33
34 ChannelDiscoveryService(XmppConnectionService service) {
35 this.service = service;
36 this.cache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
37 }
38
39 void initializeMuclumbusService() {
40 OkHttpClient.Builder builder = new OkHttpClient.Builder();
41 if (service.useTorToConnect()) {
42 try {
43 builder.proxy(HttpConnectionManager.getProxy());
44 } catch (IOException e) {
45 throw new RuntimeException("Unable to use Tor proxy", e);
46 }
47 }
48 Retrofit retrofit = new Retrofit.Builder()
49 .client(builder.build())
50 .baseUrl(Config.CHANNEL_DISCOVERY)
51 .addConverterFactory(GsonConverterFactory.create())
52 .callbackExecutor(Executors.newSingleThreadExecutor())
53 .build();
54 this.muclumbusService = retrofit.create(MuclumbusService.class);
55 }
56
57 void discover(String query, OnChannelSearchResultsFound onChannelSearchResultsFound) {
58 final boolean all = query == null || query.trim().isEmpty();
59 Log.d(Config.LOGTAG, "discover channels. query=" + query);
60 List<MuclumbusService.Room> result = cache.getIfPresent(all ? "" : query);
61 if (result != null) {
62 onChannelSearchResultsFound.onChannelSearchResultsFound(result);
63 return;
64 }
65 if (all) {
66 discoverChannels(onChannelSearchResultsFound);
67 } else {
68 discoverChannels(query, onChannelSearchResultsFound);
69 }
70 }
71
72 private void discoverChannels(OnChannelSearchResultsFound listener) {
73 Call<MuclumbusService.Rooms> call = muclumbusService.getRooms(1);
74 try {
75 call.enqueue(new Callback<MuclumbusService.Rooms>() {
76 @Override
77 public void onResponse(@NonNull Call<MuclumbusService.Rooms> call, @NonNull Response<MuclumbusService.Rooms> response) {
78 final MuclumbusService.Rooms body = response.body();
79 if (body == null) {
80 Log.d(Config.LOGTAG, "code from muclumbus=" + response.code());
81 listener.onChannelSearchResultsFound(Collections.emptyList());
82 return;
83 }
84 cache.put("", body.items);
85 listener.onChannelSearchResultsFound(body.items);
86 }
87
88 @Override
89 public void onFailure(@NonNull Call<MuclumbusService.Rooms> call, @NonNull Throwable throwable) {
90 Log.d(Config.LOGTAG, "Unable to query muclumbus on " + Config.CHANNEL_DISCOVERY, throwable);
91 listener.onChannelSearchResultsFound(Collections.emptyList());
92 }
93 });
94 } catch (Exception e) {
95 e.printStackTrace();
96 }
97 }
98
99 private void discoverChannels(final String query, OnChannelSearchResultsFound listener) {
100 Call<MuclumbusService.SearchResult> searchResultCall = muclumbusService.search(new MuclumbusService.SearchRequest(query));
101
102 searchResultCall.enqueue(new Callback<MuclumbusService.SearchResult>() {
103 @Override
104 public void onResponse(@NonNull Call<MuclumbusService.SearchResult> call, @NonNull Response<MuclumbusService.SearchResult> response) {
105 final MuclumbusService.SearchResult body = response.body();
106 if (body == null) {
107 Log.d(Config.LOGTAG, "code from muclumbus=" + response.code());
108 listener.onChannelSearchResultsFound(Collections.emptyList());
109 return;
110 }
111 cache.put(query, body.result.items);
112 listener.onChannelSearchResultsFound(body.result.items);
113 }
114
115 @Override
116 public void onFailure(@NonNull Call<MuclumbusService.SearchResult> call, @NonNull Throwable throwable) {
117 Log.d(Config.LOGTAG, "Unable to query muclumbus on " + Config.CHANNEL_DISCOVERY, throwable);
118 listener.onChannelSearchResultsFound(Collections.emptyList());
119 }
120 });
121 }
122
123 public interface OnChannelSearchResultsFound {
124 void onChannelSearchResultsFound(List<MuclumbusService.Room> results);
125 }
126}