# (C) 2021 lifegpc
# This file is part of rssbot.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
from re import search
from typing import List
from textc import textc, timeToStr
from enum import Enum, unique
from math import ceil, floor
class BlackInfo:
__uid: int = None
op_uid: int = None
from_config: bool = False
add_time: int = None
reason: str = None
@property
def uid(self) -> int:
return self.__uid
def __init__(self, uid: int, op_uid: int = None, add_time: int = None, reason: str = None, title: str = None):
self.__uid = uid
self.op_uid = op_uid
self.from_config = True if self.op_uid is None else False
self.add_time = add_time
self.reason = reason
self.title = title
@property
def name(self) -> str:
return f"{self.uid}" if self.title is None else self.title
class BlackInfoListIter:
def __init__(self, li: List[BlackInfo]):
self.__l = li
self.__start = 0
def __next__(self) -> BlackInfo:
if self.__start >= len(self.__l):
raise StopIteration
v = self.__l[self.__start]
self.__start += 1
return v
class BlackInfoList:
def __add__(self, b):
o = BlackInfoList(self.__l)
if isinstance(b, (BlackInfoList, list)):
for i in b:
o.append(i)
elif isinstance(b, BlackInfo):
o.append(b)
return o
def __getitem__(self, i) -> BlackInfo:
return self.__l[i]
def __iadd__(self, b):
if isinstance(b, (BlackInfoList, list)):
for i in b:
self.append(i)
elif isinstance(b, BlackInfo):
self.append(b)
return self
def __init__(self, li: List[BlackInfo] = None):
self.__t = []
self.__l = []
if li is not None:
for i in li:
self.append(i)
def __iter__(self):
it = BlackInfoListIter(self.__l)
return it
def __len__(self):
return len(self.__l)
def append(self, info: BlackInfo):
if info.uid not in self.__t:
self.__l.append(info)
self.__t.append(info.uid)
def find(self, uid: int):
if uid in self.__t:
return self.__t.index(uid)
else:
return -1
def isInBlackList(self, chatId: int) -> bool:
return chatId in self.__t
class ConfigBlackList:
def __init__(self, m, s: str = None):
from rssbot import main
self._main: main = m
self.__list = []
if s is not None:
l = s.split(',')
for i in l:
if search(r'^[\+-]?[0-9]+$', i) is not None:
self.__list.append(int(i))
def getBlackList(self) -> BlackInfoList:
r = BlackInfoList()
for i in self.__list:
r.append(BlackInfo(i))
return r
def isInBlackList(self, chatId: int) -> bool:
return chatId in self.__list
class BlackList:
def __init__(self, m):
from rssbot import main
self._main: main = m
self._configBlackList = ConfigBlackList(m, self._main._setting._blackList)
self._blackList = self._main._db.getBlackList()
def ban(self, i: BlackInfo):
re = self._main._db.addBlackInfo(i)
if re:
self._blackList = self._main._db.getBlackList()
self.checkRSSList()
return re
def getBlackList(self) -> BlackInfoList:
r = self._configBlackList.getBlackList()
r += self._blackList
return r
def isInBlackList(self, chatId: int) -> bool:
if self._configBlackList.isInBlackList(chatId):
return True
if self._blackList.isInBlackList(chatId):
return True
return False
def checkRSSList(self):
li = self.getBlackList()
for i in li:
self._main._db.removeChatInChatList(i.uid)
def unban(self, userId: int):
re = self._main._db.removeFromBlackList(userId)
if re:
self._blackList = self._main._db.getBlackList()
return re
@unique
class InlineKeyBoardForBlackList(Enum):
FirstPage = 0
LastPage = 1
PrevPage = 2
NextPage = 3
Close = 4
BlackInfo = 5
BackToList = 6
Unban = 7
ConfirmUnban = 8
CancleUnban = 9
def getTextContentForBlackInfo(i: BlackInfo):
t = textc()
link = '' if i.uid < 0 else f'tg://user?id={i.uid}'
t += f'被封禁用户: {i.name}'
if i.from_config:
t += '来源:配置文件'
else:
t += '来源:数据库'
t += f'封禁操作人:{i.op_uid}'
t += f'封禁时间:{timeToStr(i.add_time)}'
t += f'封禁理由:{i.reason}'
return t.tostr()
def getTextContentForUnbanBlackInfo(i: BlackInfo):
link = '' if i.uid < 0 else f'tg://user?id={i.uid}'
return f'是否要取消封禁{i.name}?'
def getInlineKeyBoardForBlackList(bl: BlackInfoList, page: int = 1, lastPage: bool = False, itemIndex: int = None):
d = []
i = -1
lineLimit = 7
l = len(bl)
pn = ceil(l / lineLimit)
if lastPage:
page = pn
if itemIndex is not None and itemIndex >= 0:
page = floor(itemIndex / lineLimit) + 1
if l != 0:
page = max(min(pn, page), 1)
s = max(lineLimit * (page - 1), 0)
n = min(lineLimit * page, l)
while s < n:
d.append([])
i += 1
d[i].append({'text': bl[s].name, 'callback_data': f'2,{InlineKeyBoardForBlackList.BlackInfo.value},{s},{bl[s].uid}'})
s += 1
if pn != 1:
d.append([])
i += 1
if page != 1:
d[i].append({'text': '上一页', 'callback_data': f'2,{InlineKeyBoardForBlackList.PrevPage.value},{page}'})
if page != pn:
d[i].append({'text': '下一页', 'callback_data': f'2,{InlineKeyBoardForBlackList.NextPage.value},{page}'})
d.append([])
i += 1
if page != 1:
d[i].append({'text': '首页', 'callback_data': f'2,{InlineKeyBoardForBlackList.FirstPage.value}'})
if page != pn:
d[i].append({'text': '尾页', 'callback_data': f'2,{InlineKeyBoardForBlackList.LastPage.value}'})
d.append([])
i += 1
d[i].append({'text': '关闭', 'callback_data': f'2,{InlineKeyBoardForBlackList.Close.value}'})
return {'inline_keyboard': d}
def getInlineKeyBoardForBlackInfo(b: BlackInfo, index: int):
d = []
i = -1
if not b.from_config:
d.append([])
i += 1
d[i].append({'text': '取消封禁', 'callback_data': f'2,{InlineKeyBoardForBlackList.Unban.value},{index},{b.uid}'})
d.append([])
i += 1
d[i].append(
{'text': '返回', 'callback_data': f'2,{InlineKeyBoardForBlackList.BackToList.value},{index}'})
return {'inline_keyboard': d}
def getInlineKeyBoardForUnbanBlackInfo(b: BlackInfo, index: int):
d = []
i = -1
d.append([])
i += 1
d[i].append({'text': '是', 'callback_data': f'2,{InlineKeyBoardForBlackList.ConfirmUnban.value},{index},{b.uid}'})
d[i].append({'text': '否', 'callback_data': f'2,{InlineKeyBoardForBlackList.CancleUnban.value},{index},{b.uid}'})
return {'inline_keyboard': d}