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])