import time
from datetime import datetime
from core.buddy_service import BuddyService
from core.chat_blob import ChatBlob
from core.command_param_types import Options, Int, Any, Character, Const
from core.db import DB
from core.decorators import instance, event, command
from core.dict_object import DictObject
from core.job_scheduler import JobScheduler
from core.logger import Logger
from core.text import Text
from core.igncore import IgnCore
from modules.core.accounting.services.account_service import AccountService
from modules.core.ban.ban_service import BanService
@instance()
class MailController:
def inject(self, registry):
self.logger = Logger(__name__)
self.bot: IgnCore = registry.get_instance("bot")
self.db: DB = registry.get_instance("db")
self.text: Text = registry.get_instance("text")
self.ban: BanService = registry.get_instance("ban_service")
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
self.job_schedule: JobScheduler = registry.get_instance("job_scheduler")
self.account_service: AccountService = registry.get_instance("account_service")
def pre_start(self):
self.db.exec(
"CREATE TABLE IF NOT EXISTS mail("
"id int primary key auto_increment, "
"text text, "
"recipient int not null, "
"sender int not null, "
"sent_at int not null, "
"`read` int not null default 0)")
@event(event_type="connect", description="register players with pending mails")
def connect_event(self, _, _1):
data = self.db.query(
"SELECT a.char_id from mail m "
"left join account a ON a.main = m.recipient "
"WHERE `read` = 0 and (a.disabled = 0 and a.member=1) "
"group by a.char_id")
for row in data:
self.buddy_service.add_buddy(row.char_id, "mail")
@event(event_type="member_logon", description="Send mails on logon")
def logon_event(self, _, data):
if not self.bot.is_ready():
return
if not self.account_service.simple_checks(data.account):
return
if "mail" in self.buddy_service.get_buddy(data.packet.char_id)["types"]:
self.job_schedule.delayed_job(self.send_mail, 16, data.packet.char_id, self.get_mails(data.packet.char_id))
def send_mail(self, _, sender, mail, greeting="Hey, you got some mails!"):
if self.buddy_service.get_buddy(sender)["online"] == 0:
return
# hotfix for
if len(mail) < 10:
self.buddy_service.remove_buddy(sender, "mail")
return
self.bot.send_mass_message(sender, f"{greeting} :: " +
self.text.paginate_single(ChatBlob("Your mails", mail)))
#####################
# Mail Management #
#####################
@command(command="mail", params=[Const('all', is_optional=True)], description="Show your mails",
access_level="member")
def mail_show(self, sender, const_all):
mails, title = None, "You dont have any unread mails."
if const_all:
mails, title = self.get_mails(sender.sender.char_id, True), "All your recent Mails"
else:
mails, title = self.get_mails(sender.sender.char_id), "Your unread mails"
if mails:
self.bot.send_private_message(sender.sender.char_id, ChatBlob(title, mails))
else:
return title
@command(command="mail", params=[Options(["read"]), Int("ID")],
description="mark a mail as read", access_level="member")
def mail_read(self, sender, _, mail_id):
row = self.db.exec(
"UPDATE mail set `read` = 1 where recipient=(SELECT main from account where char_id=? LIMIT 1) and id=?",
[sender.sender.char_id, mail_id])
if len(self.get_mails(sender.sender.char_id)) < 10:
alts = self.account_service.get_alts(sender.sender.char_id)
for i in alts:
self.buddy_service.remove_buddy(i.char_id, "mail")
if row == 0:
return f"You dont have an unread mail with the ID {mail_id}."
elif row == 1:
return f"The mail with the ID {mail_id} has been marked as read."
else:
return "Something went wrong. please contact an administrator."
@command(command="mail", params=[Options(["delete"]), Int("ID")],
description="mark a mail as read", access_level="member")
def mail_delete(self, sender, _, mail_id):
row = self.db.exec(
"DELETE FROM mail where recipient=(SELECT main from account where char_id=? LIMIT 1) and id=?",
[sender.sender.char_id, mail_id])
if len(self.get_mails(sender.sender.char_id)) < 10:
alts = self.account_service.get_alts(sender.sender.char_id)
for i in alts:
self.buddy_service.remove_buddy(i.char_id, "mail")
if row == 0:
return f"You dont have a mail with the ID {mail_id}."
elif row == 1:
return f"The mail with the ID {mail_id} has been deleted."
else:
return "Something went wrong. please contact an administrator."
@command(command="mail", params=[Options(["send"]), Character("recipient"), Any("text")],
description="Send a mail to someone", access_level="member")
def mail_send(self, sender, _, receiver, message):
if not receiver.char_id:
return f"Character {receiver.name} not found."
recipient = self.account_service.get_account(receiver.char_id)
if not recipient:
return f"No account for {receiver.name} found."
# if recipient.member == -1 or recipient.disabled == 1:
if not self.account_service.simple_checks(recipient):
return f"The Character {recipient.name} has " \
f"no active account in ."
self.db.exec("INSERT INTO mail(sender, recipient, text, sent_at) VALUES(?, ?, ?, ?)",
[sender.sender.char_id, recipient.main, message, time.time()])
alts = self.account_service.get_alts(recipient.char_id)
for i in alts:
buddy = self.buddy_service.get_buddy(i.char_id) or []
if "mail" not in buddy:
if i.member == -1:
continue
self.buddy_service.add_buddy(i.char_id, "mail")
if self.buddy_service.is_online(i.char_id):
self.send_mail(0, i.char_id, self.get_mails(i.char_id),
f"{sender.sender.name} just sent you a mail, please read it")
return "Mail sent successfully."
@command(command="mail", params=[Const("group"), Any("group"), Any("text")],
description="Send a mail to a group of players", sub_command='sendgroup', access_level="moderator")
def mail_send_group(self, sender, _, recipient, message):
group = self.account_service.get_group_tag(recipient)
users = []
if group:
# if group == "all":
# if sender.sender.access_level['level'] > 20:
# return "This group is unavailable."
# users = self.account_service.get_all_members()
# else:
users = self.account_service.get_by_group(group)
elif not group:
return f"Sorry, but the group {recipient} does not exist. " \
f"The following groups are defined: " \
f"admin, council, [all - admin only group], moderator " \
f"and leaders."
count = 0
readers = []
if group != "all":
message += f"
» This mail has been sent to the " \
f"{group} group."
else:
message += f"
» This mail has been sent to everyone."
mails = []
for user in users:
if user.main == user.char_id:
mails.append((sender.sender.char_id, user.main, message, time.time()))
count += 1
if user.online == 1:
readers.append(DictObject({"name": user.name, "char_id": user.char_id}))
with self.db.pool.get_connection() as conn:
with conn.cursor() as cur:
cur.executemany("INSERT INTO mail(sender, recipient, text, sent_at) VALUES(?, ?, ?, ?)", mails)
for user in readers:
self.send_mail(0, user.char_id, self.get_mails(user.char_id),
greeting=f"{sender.sender.name} just sent you a group mail, "
f"please read it!")
return f"I've sent the {count} mails to the group " \
f"{group} for you. " \
f"A total of {len(readers)} characters from this group are online, " \
f"the have been notified."
def get_single_mail(self, char_id, mail_id):
return ChatBlob(f"Your Mail with the ID {mail_id}", self.format_mail(self.db.query_single(
"SELECT * FROM mail where recipient=(SELECT main from account where char_id=?) and id = ?", [char_id, id])))
def get_mails(self, char_id, all_mails=False):
if all_mails:
data = self.db.query(
"SELECT * FROM mail where recipient=(SELECT main from account where char_id=?) order by id desc",
[char_id])
else:
data = self.db.query(
"SELECT * FROM mail where recipient=(SELECT main from account where char_id=?) and `read`=0 "
"order by id desc",
[char_id])
blob = ""
for row in data:
blob += self.format_mail(row) + "
"
return blob
def format_mail(self, mail):
# noinspection LongLine
return \
f"""
{self.bot.character_service.resolve_char_to_name(mail.sender) if mail.sender != 0 else "IGNCOM"} sent you a mail on {datetime.utcfromtimestamp(mail.sent_at).strftime("%d.%m.%Y - %H:%M:%S")}:
{mail.text}
- [{self.text.make_tellcmd('Mark as read', f'mail read {mail.id}')}] [{self.text.make_tellcmd('DELETE', f'mail delete {mail.id}')}]
"""
@event(event_type="main_changed", description="Fix mails")
def fix_mails(self, _, data):
self.db.exec("UPDATE mail set recipient=? where recipient=?", [data.new_main_id, data.old_main_id])