Code for banning

This commit is contained in:
ekardnam 2019-07-06 08:17:31 +02:00
parent b9514b7bfc
commit 0034b21905
2 changed files with 54 additions and 46 deletions

View file

@ -21,17 +21,13 @@ package org.congressodeiradicali.karlmarx
import cats.instances.future._
import cats.syntax.functor._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.api.declarative.whenOrElse
import com.bot4s.telegram.api.declarative.Commands
import com.bot4s.telegram.api.declarative.{Commands, whenOrElse}
import com.bot4s.telegram.clients.ScalajHttpClient
import com.bot4s.telegram.future.{Polling, TelegramBot}
import com.bot4s.telegram.methods.GetChatMember
import com.bot4s.telegram.models.{ChatId, ChatType, MemberStatus, Message, User}
import com.bot4s.telegram.models.{ChatType, Message}
import slogging.{LogLevel, LoggerConfig, PrintLoggerFactory}
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success}
import scala.concurrent.Future
class Bot(val token: String) extends TelegramBot
with Polling
@ -45,6 +41,7 @@ class Bot(val token: String) extends TelegramBot
override val client: RequestHandler[Future] = new ScalajHttpClient(token)
def getLogger() = logger
/**
* Ensures a message is sent from a user and not from the chat
@ -75,27 +72,40 @@ class Bot(val token: String) extends TelegramBot
val user = new BotUser(msg.from.get, msg.chat, this)
// if there is an error we cannot now whether the user is an admin or not
// but it's safe in any case to reply as if the user was not an admin
user.isAdmin.getOrElse(false) || user.isCreator.getOrElse(false)
user.isAdmin || user.isCreator
} else {
false
}
def canBan(msg: Message): Boolean =
if (fromActualUser(msg) && fromGroup(msg)) {
// it should be an actual user and a message from a group
// check the user member status
// get is safe as fromActualUser is called first
val user = new BotUser(msg.from.get, msg.chat, this)
// if there is an error we cannot now whether the user is an admin or not
// but it's safe in any case to reply as if the user was not an admin
user.canBanUsers
} else {
false
}
onCommand("license") { implicit msg =>
reply(" karl-marx is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n karl-marx is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with karl-marx. If not, see <https://www.gnu.org/licenses/>.").void
}
whenOrElse(onCommand("ban"), fromAdmin) { implicit msg =>
whenOrElse(onCommand("ban"), canBan) { implicit msg =>
msg.replyToMessage match {
case Some(message) => {
message.from match {
case Some(u) => {
val user = new BotUser(u, message.chat, this)
val isAdmin = user.isAdmin
if (isAdmin.isSuccess) {
if (!isAdmin.get) {
if (user.initSuccessful()) {
if (!user.isAdmin && !user.isCreator) {
user.ban
reply(localizer.getString("ban.successful")).void
} else reply(localizer.getString("ban.failed_ban_admin")).void
@ -109,12 +119,4 @@ class Bot(val token: String) extends TelegramBot
reply(localizer.getString("ban.unauthorized")).void
}
whenOrElse(onCommand("kick"), fromAdmin) { implicit msg =>
} /*else*/ { implicit msg =>
}
}

View file

@ -17,58 +17,64 @@
package org.congressodeiradicali.karlmarx
import com.bot4s.telegram.methods.GetChatMember
import com.bot4s.telegram.methods.{GetChatMember, KickChatMember, UnbanChatMember}
import com.bot4s.telegram.models.{Chat, ChatId, ChatMember, MemberStatus, User}
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.{Failure, Success, Try}
import util.control.Breaks._
class BotUser(private val user: User, private val chat: Chat, private val bot: Bot) {
def ban() : Unit = {
// ban works by sending the kick user request
bot.request(KickChatMember(ChatId.fromChat(chat.id), user.id))
}
def kick() : Unit = {
// kick works by kicking and then unbanning the user
bot.request(KickChatMember(ChatId.fromChat(chat.id), user.id))
bot.request(UnbanChatMember(ChatId.fromChat(chat.id), user.id))
}
// lazy attribute initialized on the first successful request
private var chatMember : Option[ChatMember] = None
private var chatMember : ChatMember = {
val maxRetryTimes: Int = 10
var chatMember: ChatMember = null
def getChatMember() : Try[ChatMember] = chatMember match {
case None => {
breakable {
for (time <- 0 to maxRetryTimes) {
Await.ready(bot.request(GetChatMember(ChatId.fromChat(chat.id), user.id)), Duration.Inf).value.get match {
case Success(cm) => {
chatMember = Some(cm)
Success(cm)
chatMember = cm
break
}
case Failure(err) => {
bot.getLogger().error(s"Error when requesting ChatMember data for user ${user.id}")
bot.getLogger().error(err.getLocalizedMessage)
}
case Failure(err) => Failure(err)
}
}
case Some(cm) => Success(cm)
}
def isCreator() : Try[Boolean] = {
getChatMember.map(cm => cm.status == MemberStatus.Creator)
if (chatMember == null) {
// after all retries it still has failed the request
// probably there is a problem with the network or the Telegram API is down
// this should be notified
bot.getLogger().error(s"Could not request ChatMember data after ${maxRetryTimes} requests\n Is network up?")
null
} else chatMember
}
def isAdmin() : Try[Boolean] = {
getChatMember.map(cm => cm.status == MemberStatus.Administrator)
}
def initSuccessful() : Boolean = chatMember != null
def isKicked() : Try[Boolean] = {
getChatMember.map(cm => cm.status == MemberStatus.Kicked)
}
def isCreator: Boolean = if (chatMember != null) chatMember.status == MemberStatus.Creator else false
def isAdmin : Boolean = if (chatMember != null) chatMember.status == MemberStatus.Administrator else false
def isMember : Boolean = if (chatMember != null) chatMember.status == MemberStatus.Member else false
def isKicked : Boolean = if (chatMember != null) chatMember.status == MemberStatus.Kicked else false
def isMember() : Try[Boolean] = {
getChatMember.map(cm => cm.status == MemberStatus.Member)
}
def hasLeft() : Try[Boolean] = {
getChatMember.map(cm => cm.status == MemberStatus.Left)
}
def canBanUsers : Boolean = if (chatMember != null) chatMember.canRestrictMembers.getOrElse(false) else false
}