MySQL no longer supported, antispam thing remaded
This commit is contained in:
parent
cc109af0cf
commit
3cac828cae
11
README.md
11
README.md
|
@ -43,7 +43,7 @@
|
|||
|
||||
Теперь заходим в директорию бота (`cd dan63047pythonbot/`) и устанавливаем необходимые библиотеки:
|
||||
|
||||
`pip3 install vk-api pyowm Wikipedia-API PyMySQL --user`
|
||||
`pip3 install vk-api pyowm Wikipedia-API --user`
|
||||
|
||||
Эта команда установит все необходимые библиотеки для работы бота.
|
||||
|
||||
|
@ -58,18 +58,11 @@ admins = [276193568, 629085267] # Список ид аккаунтов адми
|
|||
vk_service_token = "vk_service_token" # Сервисный ключ доступа для команды !image. Оставьте None, если хотите выключить эту команду
|
||||
album_for_command = 269199619 # Цифровой ид альбома для команды !image. Оставьте None, если хотите выключить эту команду
|
||||
openweathermap_api_key = 'openweathermap_api_key' # Ключ OpenWeather API. Оставьте None, если хотите выключить команду !weather
|
||||
use_database = True # False, если вы не планируете использовать MySQL базу данных, иначе следующие 4 строки обязательны
|
||||
mysql_host = 'pythonanywhere_nickname.mysql.pythonanywhere-services.com' # ссылка на хост БД. Вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere
|
||||
mysql_user = 'pythonanywhere_nickname' # Ваш никнейм на pythonanywhere
|
||||
mysql_pass = 'qwerty123' # Пароль, созданный вами для БД
|
||||
mysql_db = 'pythonanywhere_nickname$default' # Название вашей БД. Вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere. Так же вместо default может быть ваше название БД
|
||||
```
|
||||
## Если вы будете использовать команду !image
|
||||
Разберёмся с костылём для метода `photos.get`: Идем на `vk.com/dev`, нажимаем на *Мои приложения* и кликаем по *Создать приложение*. Новое приложение может называться как угодно, от него нам необходимо всего лишь сервисный ключ доступа, который можно найти, если нажать на *Настройки*
|
||||
## Если вы будете использовать команду !weather
|
||||
Перейдите по `openweathermap.org`, пройдите там регистрацию и создайте API ключ
|
||||
## Если вы решите использовать MySQL БД (давно не тестировалось, может не работать)
|
||||
Вам необходимо будет купить тариф на pythonanywhere, где есть поддержка MySQL базы данных, с которой бот будет работать. Тыкаем на *Databases* в шапке сайта. Создаём пароль для вашей базы данных. По умолчанию будет создана база данных с названием `your_nickname$default`, но вы можете создать БД со своим названием.
|
||||
## Запуск бота
|
||||
Если аккаунт платный: в pythonanywhere тыкаем на *Tasks*, создаём и запускаем в *Always-on tasks* задачу `python3.8 /home/pythonanywhere_nickname/dan63047pythonbot/longpulling.py`, где вместо pythonanywhere_nickname должен быть ваш никнейм на pythonanywhere. После небольшого тупления pythonanywhere запустит вашего бота.
|
||||
|
||||
|
@ -94,9 +87,7 @@ mysql_db = 'pythonanywhere_nickname$default' # Название вашей БД.
|
|||
* [vk_api](https://github.com/python273/vk_api) — модуль для создания скриптов для социальной сети Вконтакте
|
||||
* [pyowm](https://github.com/csparpa/pyowm) — модуль для получения погоды через OpenWeather API
|
||||
* [Wikipedia-API](https://github.com/martin-majlis/Wikipedia-API) — модуль для получения статей из Wikipedia
|
||||
* [PyMySQL](https://github.com/PyMySQL/PyMySQL/) — Pure Python MySQL Client
|
||||
# Дополнительно
|
||||
|
||||
Автор бота: [Даниил Михайлов](https://vk.com/dan63047)
|
||||
|
||||
Буду рад помощи и поддержке
|
||||
|
|
213
dan63047VKbot.py
213
dan63047VKbot.py
|
@ -43,6 +43,7 @@ def log(warning, text):
|
|||
print(msg)
|
||||
|
||||
bot = {}
|
||||
SPAMMER_LIST = {}
|
||||
errors_array = {"access": "Отказано в доступе",
|
||||
"miss_argument": "Отсуствует аргумент",
|
||||
"command_off": "Команда отключена",
|
||||
|
@ -94,156 +95,61 @@ except Exception:
|
|||
class Database_worker():
|
||||
|
||||
def __init__(self):
|
||||
if config.use_database:
|
||||
log(False, "Trying to connect to database")
|
||||
try:
|
||||
self._CON = pymysql.connect(
|
||||
host=config.mysql_host,
|
||||
user=config.mysql_user,
|
||||
password=config.mysql_pass,
|
||||
db=config.mysql_db,
|
||||
charset='utf8mb4',
|
||||
cursorclass=DictCursor
|
||||
)
|
||||
cur = self._CON.cursor()
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to connect to database: {str(e)}")
|
||||
try:
|
||||
cur.execute("SELECT * FROM bot_users")
|
||||
except:
|
||||
cur.execute("CREATE TABLE bot_users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, chat_id INT UNSIGNED, awaiting VARCHAR(128), access TINYINT, midnight BOOL, new_post BOOL, admin_mode BOOL, game_wins INT UNSIGNED, game_defeats INT UNSIGNED, game_draws INT UNSIGNED, banned BOOL)")
|
||||
cur.close()
|
||||
log(False, "Database connection established")
|
||||
else:
|
||||
log(False, "Bot will use JSON file as database")
|
||||
try:
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
except Exception:
|
||||
log(True, "data.json is not exist, it will be created soon")
|
||||
self._DATA_DIST = {"users": {}}
|
||||
try:
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
except Exception:
|
||||
log(True, "data.json is not exist, it will be created")
|
||||
self._DATA_DIST = {"users": {}, "spammers": []}
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def set_new_user(self, peer_id, midnight=False, awaiting=None, access=1, new_post=False, admin_mode=False, game_wins=0, game_defeats=0, game_draws=0, banned=False):
|
||||
if(config.use_database):
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute("INSERT INTO bot_users (chat_id, awaiting, access, midnight, new_post, admin_mode, game_wins, game_defeats, game_draws, banned) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
|
||||
(peer_id, awaiting, access, midnight, new_post, admin_mode, game_wins, game_defeats, game_draws, banned))
|
||||
self._CON.commit()
|
||||
cur.close()
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to add new user in database: {str(e)}")
|
||||
else:
|
||||
self._DATA_DIST['users'][peer_id] = {"awaiting": awaiting, "access": access, "midnight": midnight, "new_post": new_post,
|
||||
"admin_mode": admin_mode, "game_wins": game_wins, "game_defeats": game_defeats, "game_draws": game_draws, "banned": banned}
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
self._DATA_DIST['users'][peer_id] = {"awaiting": awaiting, "access": access, "midnight": midnight, "new_post": new_post, "admin_mode": admin_mode, "game_wins": game_wins, "game_defeats": game_defeats, "game_draws": game_draws, "banned": banned}
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def get_all_users(self):
|
||||
if not config.use_database:
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
return self._DATA_DIST['users']
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute("SELECT * FROM bot_users")
|
||||
result = cur.fetchall()
|
||||
cur.close()
|
||||
return result
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to load user from database: {str(e)}")
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
return self._DATA_DIST['users']
|
||||
|
||||
def get_from_users(self, from_id):
|
||||
if not config.use_database:
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
if not self._DATA_DIST['users'].get(str(from_id)):
|
||||
self.set_new_user(str(from_id))
|
||||
return self._DATA_DIST['users'][str(from_id)]
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute(
|
||||
"SELECT * FROM bot_users WHERE chat_id = %s", (from_id))
|
||||
result = cur.fetchall()
|
||||
cur.close()
|
||||
return result
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to load user from database: {str(e)}")
|
||||
with open("data.json", "r") as data:
|
||||
self._DATA_DIST = json.load(data)
|
||||
data.close()
|
||||
if not self._DATA_DIST['users'].get(str(from_id)):
|
||||
self.set_new_user(str(from_id))
|
||||
return self._DATA_DIST['users'][str(from_id)]
|
||||
|
||||
def get_game_stat(self):
|
||||
if not config.use_database:
|
||||
return self._DATA_DIST['users']
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute(
|
||||
"SELECT chat_id, game_wins, game_draws, game_defeats FROM bot_users WHERE game_wins > 0 OR game_draws > 0 OR game_defeats > 0")
|
||||
result = cur.fetchall()
|
||||
cur.close()
|
||||
return result
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to load stats from database: {str(e)}")
|
||||
# Info: dist cannot return only the necessary keys
|
||||
return self._DATA_DIST['users']
|
||||
|
||||
def update_user(self, chat_id, thing, new_value):
|
||||
if(config.use_database):
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute(f"UPDATE bot_users SET {thing} = %s WHERE bot_users.chat_id = %s;", (new_value, chat_id))
|
||||
self._CON.commit()
|
||||
cur.close()
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to update info about user in database: {str(e)}")
|
||||
else:
|
||||
if not self._DATA_DIST['users'][str(chat_id)].get(thing):
|
||||
if thing == "spam_list":
|
||||
self._DATA_DIST['users'][str(chat_id)][thing] = []
|
||||
self._DATA_DIST['users'][str(chat_id)][thing] = new_value
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
def update_user(self, chat_id, thing, new_value):
|
||||
self._DATA_DIST['users'][str(chat_id)][thing] = new_value
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def delete_user(self, chat_id):
|
||||
if(config.use_database):
|
||||
try:
|
||||
cur = self._CON.cursor()
|
||||
cur.execute(
|
||||
"DELETE FROM bot_users, game_defeats WHERE chat_id = %s", (chat_id))
|
||||
self._CON.commit()
|
||||
cur.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
debug_array['db_warnings'] += 1
|
||||
log(True, f"Unable to delete user from database: {str(e)}")
|
||||
return False
|
||||
else:
|
||||
self._DATA_DIST['users'].pop(str(chat_id))
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
self._DATA_DIST['users'].pop(str(chat_id))
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def add_spammer(self, user_id):
|
||||
SPAMMER_LIST.append(int(user_id))
|
||||
self._DATA_DIST["spammers"].append(int(user_id))
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def remove_spammer(self, user_id):
|
||||
SPAMMER_LIST.pop(int(user_id))
|
||||
self._DATA_DIST["spammers"].pop(int(user_id))
|
||||
open("data.json", "w").write(json.dumps(self._DATA_DIST))
|
||||
|
||||
def read_spammers(self):
|
||||
return self._DATA_DIST["spammers"]
|
||||
|
||||
|
||||
db = Database_worker()
|
||||
|
||||
|
||||
def load_users():
|
||||
try:
|
||||
log(False, "Reading database")
|
||||
get_info = db.get_all_users()
|
||||
for i in get_info:
|
||||
if config.use_database:
|
||||
bot[int(i['chat_id'])] = VkBot(int(i['chat_id']), bool(i['midnight']), i['awaiting'], int(
|
||||
i['access']), bool(i['new_post']), bool(i['admin_mode']), bool(i['banned']))
|
||||
else:
|
||||
bot[int(i)] = VkBot(int(i), bool(get_info[i]['midnight']), get_info[i]['awaiting'], int(
|
||||
get_info[i]['access']), bool(get_info[i]['new_post']), bool(get_info[i]['admin_mode']), bool(get_info[i]['banned']))
|
||||
except Exception as lol:
|
||||
debug_array['bot_warnings'] += 1
|
||||
log(True, f"Problem with creating objects: {str(lol)}")
|
||||
|
||||
|
||||
def toFixed(numObj, digits=0):
|
||||
return f"{numObj:.{digits}f}"
|
||||
|
@ -306,7 +212,6 @@ class VkBot:
|
|||
"""
|
||||
log(False, f"[BOT_{peer_id}] Created new bot-object")
|
||||
self._CHAT_ID = peer_id
|
||||
self._SPAMMER_LIST = {}
|
||||
self._AWAITING_INPUT_MODE = awaiting
|
||||
self._ACCESS_TO_ALL = access
|
||||
self._MIDNIGHT_EVENT = midnight
|
||||
|
@ -375,17 +280,19 @@ class VkBot:
|
|||
action = event.message.action
|
||||
if action['type'] == 'chat_invite_user' or action['type'] == 'chat_invite_user_by_link':
|
||||
user_info = vk.method('users.get', {'user_ids': action["member_id"], 'fields': 'verified,last_seen,sex'})
|
||||
chat_info = db.get_from_users(int(self._CHAT_ID))
|
||||
if chat_info.get("spam_list"):
|
||||
if int(action["member_id"]) in chat_info["spam_list"]:
|
||||
self.send(f'Привет, {user_info[0]["first_name"]}. К сожалению, администраторы этой беседы признали тебя спамером, поэтому мне придётся выгнать тебя отсюда')
|
||||
vk.method("messages.removeChatUser", {"chat_id": int(self._CHAT_ID)-2000000000, "member_id": action["member_id"]})
|
||||
return
|
||||
if int(action["member_id"]) in SPAMMER_LIST:
|
||||
self.send(f'[id{action["member_id"]}|Данный пользователь] находится в антиспам базе. Исключаю...')
|
||||
vk.method("messages.removeChatUser", {"chat_id": int(self._CHAT_ID)-2000000000, "member_id": action["member_id"]})
|
||||
return
|
||||
self.send(f'Добро пожаловать в беседу, {user_info[0]["first_name"]} {user_info[0]["last_name"]}')
|
||||
elif action['type'] == 'chat_kick_user':
|
||||
pass
|
||||
# user_info = vk.method('users.get', {'user_ids': action["member_id"], 'fields': 'verified,last_seen,sex'})
|
||||
# self.send(f'{user_info[0]["first_name"]} {user_info[0]["last_name"]} покинул беседу')
|
||||
if event.message.peer_id > 2000000000 and int(user_id) in SPAMMER_LIST:
|
||||
self.send(f'[id{user_id}|Данный пользователь] находится в антиспам базе. Исключаю...')
|
||||
vk.method("messages.removeChatUser", {"chat_id": int(self._CHAT_ID)-2000000000, "member_id": user_id})
|
||||
return
|
||||
if self._AWAITING_INPUT_MODE:
|
||||
if message == "Назад":
|
||||
self.change_await()
|
||||
|
@ -645,14 +552,10 @@ class VkBot:
|
|||
message = message[1].split(' ', 1)
|
||||
victum = re.search(r'id\d+', message[1])
|
||||
victum = victum[0][2:]
|
||||
if db.get_from_users(int(self._CHAT_ID)).get("spam_list"):
|
||||
chat_spammers_list = db.get_from_users(int(self._CHAT_ID))["spam_list"]
|
||||
else:
|
||||
chat_spammers_list = []
|
||||
if message[0] == "add" or message [0] == "добавить":
|
||||
if message[0] == "add" or message[0] == "добавить":
|
||||
if int(victum) != int(config.owner_id):
|
||||
if int(victum) not in chat_spammers_list:
|
||||
chat_spammers_list.append(int(victum))
|
||||
if int(victum) not in SPAMMER_LIST:
|
||||
db.add_spammer(int(victum))
|
||||
respond["text"] = "Теперь он считается спамером"
|
||||
log(False, f"[BOT_{self._CHAT_ID}] user {victum} added to spammer list")
|
||||
else:
|
||||
|
@ -661,15 +564,14 @@ class VkBot:
|
|||
log(False, f"[BOT_{self._CHAT_ID}] can't add to spammer list owner")
|
||||
elif message[0] == "remove" or message[0] == "удалить":
|
||||
if int(victum) != int(config.owner_id):
|
||||
if int(victum) in chat_spammers_list:
|
||||
chat_spammers_list.pop(int(victum))
|
||||
if int(victum) in SPAMMER_LIST:
|
||||
db.remove_spammer(int(victum))
|
||||
respond["text"] = "Теперь он не считается спамером"
|
||||
log(False, f"[BOT_{self._CHAT_ID}] user {victum} removed to spammer list")
|
||||
else:
|
||||
respond["text"] = "Его нет в этой базе"
|
||||
else:
|
||||
log(False, f"[BOT_{self._CHAT_ID}] can't restore owner")
|
||||
db.update_user(int(self._CHAT_ID), "spam_list", chat_spammers_list)
|
||||
except IndexError:
|
||||
respond['text'] = errors_array["miss_argument"]
|
||||
except Exception as e:
|
||||
|
@ -758,14 +660,7 @@ class VkBot:
|
|||
return answer
|
||||
|
||||
def game(self, thing, user_id):
|
||||
data = db.get_from_users(user_id)
|
||||
if (config.use_database):
|
||||
if len(data) == 0:
|
||||
create_new_bot_object(user_id)
|
||||
data = db.get_from_users(user_id)
|
||||
d = data[0]
|
||||
else:
|
||||
d = data
|
||||
d = db.get_from_users(user_id)
|
||||
if thing == "статистика":
|
||||
try:
|
||||
winrate = (d['game_wins']/(d['game_wins'] +
|
||||
|
|
|
@ -41,18 +41,20 @@ def bots():
|
|||
log_msg += atch
|
||||
dan63047VKbot.log(False, log_msg)
|
||||
dan63047VKbot.debug_array['messages_get'] += 1
|
||||
if int(event.message.peer_id) not in dan63047VKbot.bot:
|
||||
dan63047VKbot.create_new_bot_object(event.message.peer_id)
|
||||
if event.message.peer_id not in dan63047VKbot.bot:
|
||||
u = dan63047VKbot.db.get_all_users()
|
||||
if str(event.message.peer_id) not in u:
|
||||
dan63047VKbot.create_new_bot_object(event.message.peer_id)
|
||||
else:
|
||||
i = dan63047VKbot.db.get_from_users(event.message.peer_id)
|
||||
dan63047VKbot.bot[event.message.peer_id] = dan63047VKbot.VkBot(event.message.peer_id, bool(i['midnight']), i['awaiting'], int(i['access']), bool(i['new_post']), bool(i['admin_mode']), bool(i['banned']))
|
||||
dan63047VKbot.bot[event.message.peer_id].get_message(event)
|
||||
elif event.type == dan63047VKbot.VkBotEventType.WALL_POST_NEW:
|
||||
if event.object.post_type == "post":
|
||||
dan63047VKbot.log(False, f"[NEW_POST] id{event.object.id}")
|
||||
users = dan63047VKbot.db.get_all_users()
|
||||
for i in users:
|
||||
if (config.use_database):
|
||||
dan63047VKbot.bot[int(i['chat_id'])].event("post", event.object)
|
||||
else:
|
||||
dan63047VKbot.bot[int(i)].event("post", event.object)
|
||||
dan63047VKbot.bot[int(i)].event("post", event.object)
|
||||
else:
|
||||
dan63047VKbot.log(False, f"[NEW_OFFER] id{event.object.id}")
|
||||
elif event.type == dan63047VKbot.VkBotEventType.MESSAGE_DENY:
|
||||
|
@ -75,17 +77,14 @@ def midnight():
|
|||
dan63047VKbot.log(False, "[EVENT_STARTED] \"Midnight\"")
|
||||
users = dan63047VKbot.db.get_all_users()
|
||||
for i in users:
|
||||
if (config.use_database):
|
||||
dan63047VKbot.bot[int(i['chat_id'])].event("midnight")
|
||||
else:
|
||||
dan63047VKbot.bot[int(i)].event("midnight")
|
||||
dan63047VKbot.bot[int(i)].event("midnight")
|
||||
dan63047VKbot.log(False, "[EVENT_ENDED] \"Midnight\"")
|
||||
time.sleep(1)
|
||||
else:
|
||||
time.sleep(0.50)
|
||||
|
||||
|
||||
dan63047VKbot.load_users()
|
||||
dan63047VKbot.SPAMMER_LIST = dan63047VKbot.db.read_spammers()
|
||||
tread_bots = threading.Thread(target=bots)
|
||||
tread_midnight = threading.Thread(target=midnight, daemon=True)
|
||||
tread_bots.start()
|
||||
|
|
Loading…
Reference in New Issue