165 lines
5.8 KiB
Java
165 lines
5.8 KiB
Java
package it.cavallium;
|
|
|
|
import it.tdlight.jni.TdApi;
|
|
import it.tdlight.jni.TdApi.AuthorizationState;
|
|
import it.tdlight.jni.TdApi.AuthorizationStateReady;
|
|
import it.tdlight.jni.TdApi.Chat;
|
|
import it.tdlight.jni.TdApi.ChatMemberStatusAdministrator;
|
|
import it.tdlight.jni.TdApi.ChatMemberStatusCreator;
|
|
import it.tdlight.jni.TdApi.GetSupergroupFullInfo;
|
|
import it.tdlight.jni.TdApi.Object;
|
|
import it.tdlight.jni.TdApi.Supergroup;
|
|
import it.tdlight.jni.TdApi.SupergroupFullInfo;
|
|
import it.tdlight.jni.TdApi.Update;
|
|
import it.tdlight.jni.TdApi.UpdateAuthorizationState;
|
|
import it.tdlight.jni.TdApi.UpdateNewChat;
|
|
import it.tdlight.jni.TdApi.UpdateSupergroup;
|
|
import it.tdlight.jni.TdApi.UpdateSupergroupFullInfo;
|
|
import it.tdlight.tdlibsession.td.TdResult;
|
|
import it.tdlight.tdlibsession.td.easy.AsyncTdEasy;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.StringJoiner;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.stream.Collectors;
|
|
import reactor.core.publisher.EmitterProcessor;
|
|
import reactor.core.publisher.Flux;
|
|
import reactor.core.publisher.Mono;
|
|
import reactor.core.scheduler.Scheduler;
|
|
import reactor.core.scheduler.Schedulers;
|
|
|
|
public class TransferClient {
|
|
|
|
private final String alias;
|
|
private final AsyncTdEasy client;
|
|
private final ConcurrentHashMap<Integer, Supergroup> supergroupInfos = new ConcurrentHashMap<>();
|
|
private final ConcurrentHashMap<Integer, SupergroupFullInfo> supergroupFullInfos = new ConcurrentHashMap<>();
|
|
private final ConcurrentHashMap<Long, Chat> chats = new ConcurrentHashMap<>();
|
|
private final EmitterProcessor<ItemUpdate<SupergroupInfo>> usefulSupergroups = EmitterProcessor.create();
|
|
private final Scheduler scheduler;
|
|
|
|
public TransferClient(String alias, AsyncTdEasy client) {
|
|
this.alias = alias;
|
|
this.client = client;
|
|
|
|
this.scheduler = Schedulers.boundedElastic();
|
|
|
|
this.client.getIncomingUpdates()
|
|
.subscribeOn(scheduler)
|
|
.publishOn(scheduler)
|
|
.flatMap(this::onUpdate)
|
|
.subscribe();
|
|
}
|
|
|
|
private Mono<Void> onUpdate(Update update) {
|
|
switch (update.getConstructor()) {
|
|
case UpdateSupergroup.CONSTRUCTOR:
|
|
return this.onUpdateSupergroup(((UpdateSupergroup) update).supergroup);
|
|
case UpdateSupergroupFullInfo.CONSTRUCTOR:
|
|
return this.onUpdateSupergroupFullInfo(
|
|
((UpdateSupergroupFullInfo) update).supergroupId,
|
|
((UpdateSupergroupFullInfo) update).supergroupFullInfo);
|
|
case UpdateNewChat.CONSTRUCTOR:
|
|
return this.onChat(((UpdateNewChat) update).chat);
|
|
case UpdateAuthorizationState.CONSTRUCTOR:
|
|
return this.onUpdateAuthorizationState(((UpdateAuthorizationState) update).authorizationState);
|
|
default:
|
|
return Mono.empty();
|
|
}
|
|
}
|
|
|
|
private Mono<Void> onUpdateAuthorizationState(AuthorizationState authorizationState) {
|
|
switch (authorizationState.getConstructor()) {
|
|
case AuthorizationStateReady.CONSTRUCTOR:
|
|
return TransferUtils.getAllHomeChats(this).flatMap(this::onChat).then();
|
|
default:
|
|
return Mono.empty();
|
|
}
|
|
}
|
|
|
|
private Mono<Void> onChat(Chat chat) {
|
|
if (chats.put(chat.id, chat) == null) {
|
|
// ok
|
|
}
|
|
return Mono.empty();
|
|
}
|
|
|
|
private Mono<Void> onUpdateSupergroup(Supergroup supergroup) {
|
|
// Fast checks to ignore most unwanted infos
|
|
if (!supergroup.isChannel
|
|
&&
|
|
(supergroup.status.getConstructor() == ChatMemberStatusAdministrator.CONSTRUCTOR
|
|
|| supergroup.status.getConstructor() == ChatMemberStatusCreator.CONSTRUCTOR)) {
|
|
if (supergroupInfos.put(supergroup.id, supergroup) == null) {
|
|
return this
|
|
.<SupergroupFullInfo>send(new GetSupergroupFullInfo(supergroup.id))
|
|
.filter(TdResult::succeeded)
|
|
.map(TdResult::result)
|
|
.flatMap(supergroupFullInfo -> onUpdateSupergroupFullInfo(supergroup.id, supergroupFullInfo));
|
|
}
|
|
}
|
|
return Mono.empty();
|
|
}
|
|
|
|
private Mono<Void> onUpdateSupergroupFullInfo(int id, SupergroupFullInfo supergroupFullInfo) {
|
|
if (supergroupFullInfos.put(id, supergroupFullInfo) == null) {
|
|
var sgInfo = getSupergroupBaseChatInfo(id);
|
|
sgInfo.ifPresent(t -> this.usefulSupergroups.onNext(new ItemUpdate<>(false, t)));
|
|
// ok
|
|
}
|
|
return Mono.empty();
|
|
}
|
|
|
|
/**
|
|
* Sends request to TDLib.
|
|
* @return The response or {@link TdApi.Error}.
|
|
*/
|
|
public <T extends Object> Mono<TdResult<T>> send(TdApi.Function request) {
|
|
return client.<T>send(request).publishOn(scheduler);
|
|
}
|
|
|
|
public Set<BaseChatInfo> getAdminSupergroups(boolean requireCanRestrictMembers, boolean requireCanInviteUsers) {
|
|
return supergroupFullInfos.entrySet().stream().flatMap(entry -> {
|
|
int id = entry.getKey();
|
|
return getSupergroupBaseChatInfo(id).filter(sgInfo -> {
|
|
if (!sgInfo.canRestrictMembers() && requireCanRestrictMembers) {
|
|
return false;
|
|
}
|
|
if (!sgInfo.canInviteUsers() && requireCanInviteUsers) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}).map(SupergroupInfo::getBaseChatInfo).stream();
|
|
}).collect(Collectors.toSet());
|
|
}
|
|
|
|
private Optional<SupergroupInfo> getSupergroupBaseChatInfo(int id) {
|
|
var chatInfo = chats.get(TransferUtils.chatEntityIdToChatId(id, TChatType.SUPERGROUP));
|
|
var baseInfo = supergroupInfos.get(id);
|
|
if (chatInfo == null || baseInfo == null) {
|
|
return Optional.empty();
|
|
} else {
|
|
var baseChatInfo = new BaseChatInfo(id, chatInfo.title);
|
|
if (baseInfo.status.getConstructor() == ChatMemberStatusCreator.CONSTRUCTOR) {
|
|
var sgInfo = new SupergroupInfo(baseChatInfo, true, true);
|
|
return Optional.of(sgInfo);
|
|
} else if (baseInfo.status.getConstructor() == ChatMemberStatusAdministrator.CONSTRUCTOR) {
|
|
var adminStatus = (ChatMemberStatusAdministrator) baseInfo.status;
|
|
var sgInfo = new SupergroupInfo(baseChatInfo, adminStatus.canRestrictMembers, adminStatus.canInviteUsers);
|
|
return Optional.of(sgInfo);
|
|
} else {
|
|
return Optional.empty();
|
|
}
|
|
}
|
|
}
|
|
|
|
public Flux<ItemUpdate<SupergroupInfo>> subscribeAdminSupergroups() {
|
|
return usefulSupergroups.hide();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return alias;
|
|
}
|
|
}
|