Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
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.tyrbot import Tyrbot
|
||||
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: Tyrbot = 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 data.account.disabled == 1:
|
||||
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"<red>{greeting}</red> <yellow>::</yellow> " +
|
||||
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):
|
||||
if const_all:
|
||||
mails = self.get_mails(sender.sender.char_id, True)
|
||||
if mails:
|
||||
self.bot.send_private_message(sender.sender.char_id, ChatBlob("All your recent Mails", mails))
|
||||
else:
|
||||
return "You dont have any mails."
|
||||
else:
|
||||
mails = self.get_mails(sender.sender.char_id)
|
||||
if mails:
|
||||
self.bot.send_private_message(sender.sender.char_id, ChatBlob("Your unread mails", mails))
|
||||
else:
|
||||
return "You dont have any unread mails."
|
||||
|
||||
@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 <highlight>{mail_id}</highlight>."
|
||||
elif row == 1:
|
||||
return f"The mail with the ID <highlight>{mail_id}</highlight> 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 <highlight>{mail_id}</highlight>."
|
||||
elif row == 1:
|
||||
return f"The mail with the ID <highlight>{mail_id}</highlight> 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 <highlight>{receiver.name}</highlight> not found."
|
||||
recipient = self.account_service.get_account(receiver.char_id)
|
||||
if not recipient:
|
||||
return f"No account for <highlight>{receiver.name}</highlight> found."
|
||||
if recipient.member == -1 or recipient.disabled == 1:
|
||||
return f"The Character <highlight>{recipient.name}</highlight> has " \
|
||||
f"no active account in <highlight><myname></highlight>."
|
||||
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 <highlight>{recipient}</highlight> does not exist. " \
|
||||
f"The following groups are defined: " \
|
||||
f"<highlight>admin, council, [all - admin only group], moderator</highlight> " \
|
||||
f"and <highlight>leaders</highlight>."
|
||||
|
||||
count = 0
|
||||
readers = []
|
||||
if group != "all":
|
||||
message += f"<br><tab><header>» This mail has been sent to the " \
|
||||
f"<highlight>{group}</highlight> group.</header>"
|
||||
else:
|
||||
message += f"<br><tab><header>» This mail has been sent to <highlight>everyone</highlight>.</header>"
|
||||
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"<highlight>{sender.sender.name}</highlight> just sent you a group mail, "
|
||||
f"please read it!")
|
||||
|
||||
return f"I've sent the <highlight>{count}</highlight> mails to the group " \
|
||||
f"<highlight>{group}</highlight> for you. " \
|
||||
f"A total of <highlight>{len(readers)}</highlight> 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) + "<br>"
|
||||
return blob
|
||||
|
||||
def format_mail(self, mail):
|
||||
# noinspection LongLine
|
||||
return \
|
||||
f"""
|
||||
<notice>{self.bot.character_service.resolve_char_to_name(mail.sender) if mail.sender != 0 else "IGNCOM"}</notice> sent you a mail on <highlight>{datetime.utcfromtimestamp(mail.sent_at).strftime("%d.%m.%Y - %H:%M:%S")}</highlight>:
|
||||
<white>{mail.text}</white>
|
||||
- <green>[{self.text.make_tellcmd('Mark as read', f'mail read {mail.id}')}] [{self.text.make_tellcmd('DELETE', f'mail delete {mail.id}')}]</green>
|
||||
"""
|
||||
|
||||
@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])
|
||||
@@ -0,0 +1,302 @@
|
||||
import random
|
||||
import textwrap
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
from queue import Queue
|
||||
|
||||
from core.buddy_service import BuddyService
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_param_types import Options, Int, Const, Any
|
||||
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.lookup.pork_service import PorkService
|
||||
from core.setting_service import SettingService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.core.accounting.preference_controller import PreferenceController
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
from modules.onlinebot.online.org_alias_controller import OrgAliasController
|
||||
from modules.standard.news.weekly_controller import WeeklyController
|
||||
from modules.standard.news.worldboss_controller import WorldBossController
|
||||
|
||||
|
||||
@instance()
|
||||
class NewsController:
|
||||
queue = Queue()
|
||||
# taken from https://app2brain.com/de/sprachen-lernen/woerter-saetze/hallo/
|
||||
greetings = ["Welcome", "Greetings", "Hey", "Namaste", "Ahoy", "Salutations", "Hola", "Ahoj", "Hallo", "Hello",
|
||||
"Hei", "Salut", "Helló", "Halló", "Ciao", "Olá", "Ahoj", "¡Hola"]
|
||||
layout = \
|
||||
"""
|
||||
<header>News</header>
|
||||
|
||||
<notice>CURRENT TIME</notice>
|
||||
hh:mm - DD.MM.YYYY
|
||||
{time}
|
||||
|
||||
<notice>ACCOUNT</notice>
|
||||
Your main is: <highlight>{main}</highlight>
|
||||
You have {alts_show} <highlight>alts</highlight> registered
|
||||
{discord}
|
||||
Preferences: {prefs}
|
||||
|
||||
<notice>NEWS</notice>
|
||||
{news}
|
||||
<notice>TIMERS</notice>
|
||||
{timers}
|
||||
<notice>POPULAR COMMANDS</notice>
|
||||
{commands}
|
||||
"""
|
||||
|
||||
def inject(self, registry):
|
||||
self.logger = Logger(__name__)
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.db: DB = registry.get_instance("db")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
self.pork: PorkService = registry.get_instance("pork_service")
|
||||
self.util: Util = registry.get_instance("util")
|
||||
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.job_schedule: JobScheduler = registry.get_instance("job_scheduler")
|
||||
self.preferences: PreferenceController = registry.get_instance("preference_controller")
|
||||
self.alias_controller: OrgAliasController = registry.get_instance("org_alias_controller")
|
||||
self.weekly: WeeklyController = registry.get_instance("weekly_controller")
|
||||
self.worldboss: WorldBossController = registry.get_instance("world_boss_controller")
|
||||
|
||||
def pre_start(self):
|
||||
self.db.exec(
|
||||
"CREATE TABLE IF NOT EXISTS news("
|
||||
"id int primary key auto_increment, "
|
||||
"text text, "
|
||||
"added_by int not null, "
|
||||
"added_at timestamp, "
|
||||
"headline int not null default 0)")
|
||||
|
||||
def start(self):
|
||||
self.commands = f" [{self.text.make_chatcmd('raids', '/tell <myname> raids')}] " \
|
||||
f"[{self.text.make_chatcmd('online', '/tell <myname> online')}]\n" \
|
||||
f" [{self.text.make_chatcmd('rules', '/tell <myname> rules')}] " \
|
||||
f"[{self.text.make_chatcmd('about', '/tell <myname> about')}]\n" \
|
||||
f" [{self.text.make_chatcmd('orgs', '/tell <myname> orgs')}] " \
|
||||
f"[{self.text.make_chatcmd('admins', '/tell <myname> admins')}]\n"
|
||||
|
||||
@event("connect", "prepare info msg")
|
||||
def prepare_info(self, _, _1):
|
||||
self.INFO = ChatBlob("Welcome", f"<font color=CCInfoText>You're getting this message,\n"
|
||||
f"because you recently joined the clan alliance\n"
|
||||
f"<highlight>The New Alliance</highlight> or in short "
|
||||
f"<highlight>TNA</highlight>.\n"
|
||||
f"I'm <notice><myname></notice>, a bot with the task to "
|
||||
f"automate a few workflows around here,\n"
|
||||
f"while making the life of everyone a bit easier.\n"
|
||||
f"\n"
|
||||
f"You can see a list of all my orgs by using "
|
||||
f"{self.text.make_tellcmd('!orgs', 'orgs')}.\n"
|
||||
f"Whenever you use {self.text.make_tellcmd('!online', 'online')} "
|
||||
f"I'll show you who's currently around.\n"
|
||||
f"We've got regular raids, you can view them by using "
|
||||
f"{self.text.make_tellcmd('!raids', 'raids')}\n"
|
||||
f"If you'd like to stay out, thats fine. Just turn all settings off here: "
|
||||
f"{self.text.make_tellcmd('here', 'prefs')}\n"
|
||||
f"\n"
|
||||
f"If you encounter any issues, my administrators will help you. just ask them, "
|
||||
f"you can find them all here: {self.text.make_tellcmd('!admins', 'admins')}\n"
|
||||
f"\n"
|
||||
f"<highlight>Thats it already. "
|
||||
f"Thank you for taking your time to read this note. See you ingame!</highlight>"
|
||||
f"</font>")
|
||||
self.INFO = f"\n<yellow>________________\n\n" \
|
||||
f" No need to <red>PANIC</red>!\n" \
|
||||
f" [{self.text.paginate_single(self.INFO)}]\n" \
|
||||
f" to our alliance!\n" \
|
||||
f"________________</yellow>"
|
||||
|
||||
@event(event_type="member_logon", description="Send news to players logging in")
|
||||
def logon_event(self, _, data):
|
||||
if not self.bot.is_ready():
|
||||
return
|
||||
if "member" in self.buddy_service.get_buddy(data.packet.char_id)["types"]:
|
||||
account = data.account
|
||||
if account.disabled == 1:
|
||||
return
|
||||
if self.db.query_single("SELECT * from org_bots where char_id=?", [data.packet.char_id]):
|
||||
return
|
||||
if account.news_spam == 1:
|
||||
if account.discord_joined == 0:
|
||||
discord = f"Your Account is <highlight>not</highlight> connected to Discord " \
|
||||
f"[{self.text.make_chatcmd('Join', '/tell <myname> discord invite')}]"
|
||||
else:
|
||||
discord = f"Your Account <highlight>is</highlight> connected to Discord as " \
|
||||
f"<highlight>[{self.alias_controller.get_alias(account.org_id)}] " \
|
||||
f"{account.name}</highlight>"
|
||||
user = self.pork.get_character_info(data.packet.char_id)
|
||||
self.job_schedule.delayed_job(self.send_news, 15, user, self.account_service.get_alts(account.main),
|
||||
discord,
|
||||
self.preferences.get_pref_view_small(account))
|
||||
if account.last_seen == 0 and self.setting_service.get_value('is_alliance_bot') == "1":
|
||||
self.bot.send_mass_message(data.packet.char_id, self.INFO)
|
||||
|
||||
@command(command="raids", params=[], description="Show the Raids", access_level="member")
|
||||
def show_raids(self, _):
|
||||
with open("data/latest_raids.txt", "r") as f:
|
||||
return self.text.format_page("Raidschedule", f.read())
|
||||
|
||||
def get_timers(self):
|
||||
events = [self.weekly.get_next_bs(),
|
||||
self.weekly.get_next_ai(),
|
||||
self.weekly.get_next_dio()]
|
||||
next_event = sorted(events, key=lambda timer_event: timer_event.start)[0]
|
||||
name = self.bot.get_char_name().upper()
|
||||
out = f" <highlight>{self.weekly.get_long_name(next_event.type)}</highlight> - "
|
||||
if next_event.is_running():
|
||||
out += f"[Ends in {self.util.time_to_readable(next_event.end - time.time())}] " \
|
||||
f"[by <highlight>{name}</highlight>]\n"
|
||||
else:
|
||||
out += f"[Starts in {self.util.time_to_readable(next_event.start - time.time())}] " \
|
||||
f"[by <highlight>{name}</highlight>]\n"
|
||||
|
||||
for timer in self.worldboss.timer_data:
|
||||
msg = self.worldboss.show_user(timer)
|
||||
if msg != "No timers cached; please try again later.":
|
||||
out += " " + msg + "\n"
|
||||
return out
|
||||
|
||||
def get_next_event(self):
|
||||
events = [self.weekly.get_next_bs(),
|
||||
self.weekly.get_next_ai(),
|
||||
self.weekly.get_next_dio()]
|
||||
return sorted(events, key=lambda timer: timer.start)[0]
|
||||
|
||||
def send_news(self, _, sender, alts, discord, prefs, auto=True):
|
||||
if auto:
|
||||
if self.buddy_service.get_buddy(sender.char_id)["online"] == 0:
|
||||
return
|
||||
timers = self.get_timers()
|
||||
next_event = self.get_next_event()
|
||||
news = self.layout.format(time=datetime.now(timezone.utc).strftime("%H:%M - %d.%m.%Y") + " [UTC-0]",
|
||||
main=alts[0].name,
|
||||
alts_show=self.text.make_chatcmd(len(alts), "/tell <myname> alts"),
|
||||
news=self.get_news(),
|
||||
timers=timers,
|
||||
commands=self.commands,
|
||||
prefs=prefs,
|
||||
discord=discord)
|
||||
name = self.weekly.get_long_name(next_event.type)
|
||||
blob = f"<yellow>{random.choice(self.greetings)} {sender.name} :: " \
|
||||
f"{self.text.format_page('Your News', textwrap.dedent(news))} </yellow> " \
|
||||
f"{f'<yellow>::</yellow> {name} running' if next_event.is_running() else ''}"
|
||||
self.bot.send_mass_message(sender.char_id, blob)
|
||||
|
||||
#####################
|
||||
# News Management #
|
||||
#####################
|
||||
|
||||
@command(command="news", params=[], description="Show the news", access_level="member")
|
||||
def show_news(self, sender):
|
||||
user = self.db.query_single("SELECT * FROM player where char_id=?", [sender.sender.char_id])
|
||||
alts = self.account_service.get_alts(sender.sender.char_id)
|
||||
if not alts:
|
||||
discord = f"Your Account is <highlight>not</highlight> connected to Discord " \
|
||||
f"[{self.text.make_chatcmd('Join', '/tell <myname> discord invite')}]"
|
||||
alts = [self.account_service.get_main(sender.sender.char_id)]
|
||||
elif alts[0].discord_joined == 0:
|
||||
discord = f"Your Account is <highlight>not</highlight> connected to Discord " \
|
||||
f"[{self.text.make_chatcmd('Join', '/tell <myname> discord invite')}]"
|
||||
else:
|
||||
prefix = ""
|
||||
if self.setting_service.get_value('is_alliance_bot') == '1':
|
||||
prefix = f"[{self.alias_controller.get_alias(alts[0].org_id)}] "
|
||||
discord = f"Your Account <highlight>is</highlight> connected to Discord as " \
|
||||
f"<highlight>{prefix}{alts[0].name}</highlight>"
|
||||
prefs = self.preferences.get_pref_view_small(alts[0]) if alts else ""
|
||||
self.send_news(0, user, alts, discord, prefs, False)
|
||||
|
||||
@command(command="news", params=[Options(["pin", "unpin"]), Int("ID")], description="Set news as headlines",
|
||||
access_level="moderator", sub_command="moderate")
|
||||
def news_pin(self, _, option, news_id):
|
||||
if option == "pin":
|
||||
row = self.db.exec("UPDATE news set headline=1 where id =?", [news_id])
|
||||
if row == 0:
|
||||
return f"There's no entry with the ID <highlight>{news_id}</highlight>, or it is already pinned."
|
||||
elif row == 1:
|
||||
return f"The entry with the ID <highlight>{news_id}</highlight> has been pinned."
|
||||
else:
|
||||
return "Multiple entries have been pinned... SHIT!"
|
||||
elif option == "unpin":
|
||||
row = self.db.exec("UPDATE news set headline=0 where id =?", [news_id])
|
||||
if row == 0:
|
||||
return f"There's no entry with the ID <highlight>{news_id}</highlight>, or it is not pinned."
|
||||
elif row == 1:
|
||||
return f"The entry with the ID <highlight>{news_id}</highlight> has been unpinned."
|
||||
else:
|
||||
return "Multiple entries have been unpinned... SHIT!"
|
||||
|
||||
@command(command="news", params=[Options(["remove", "delete", "rem", "del"]), Int("ID")],
|
||||
description="Set news as headlines", access_level="moderator", sub_command="moderate")
|
||||
def news_del(self, _, _1, news_id):
|
||||
row = self.db.exec("DELETE FROM news where id =?", [news_id])
|
||||
if row == 0:
|
||||
return f"There's no entry with the ID <highlight>{news_id}</highlight>."
|
||||
elif row == 1:
|
||||
return f"The entry with the ID <highlight>{news_id}</highlight> has been removed."
|
||||
else:
|
||||
return "Multiple entries have been deleted... SHIT!"
|
||||
|
||||
@command(command="news", params=[Const("add"), Any("text")], description="Moderate the news",
|
||||
access_level="moderator", sub_command="moderate")
|
||||
def news_add(self, sender, _, text):
|
||||
self.add_entry(text, sender.sender)
|
||||
row = DictObject(
|
||||
{"added_at": datetime.utcfromtimestamp(time.time()), "added_by": sender.sender.char_id, "headline": 0,
|
||||
"id": self.db.query_single("SELECT id from news order by id desc").id, "text": text})
|
||||
return ChatBlob(f"News entry with ID {row.id}",
|
||||
self.format_entry(row, sender.sender, sender.sender.access_level['level'] <= 30))
|
||||
|
||||
@command(command="news", params=[Options(["detail", "info", "more"]), Int("ID", is_optional=True)],
|
||||
description="Moderate the news", access_level="member")
|
||||
def news_detail(self, sender, _, news_id):
|
||||
if news_id:
|
||||
row = self.db.query_single("SELECT * from news where id=?", [news_id])
|
||||
if row:
|
||||
return ChatBlob(f"News entry with ID {news_id}",
|
||||
self.format_entry(row, sender.sender, sender.sender.access_level['level'] <= 30))
|
||||
else:
|
||||
return f"There's no entry with the ID <highlight>{news_id}</highlight>."
|
||||
else:
|
||||
return ChatBlob("The latest news", self.get_news(10000, sender.sender))
|
||||
|
||||
def get_news(self, limit=500, receiver=None):
|
||||
data = self.db.query("SELECT * from news order by ID desc")
|
||||
normal = ""
|
||||
headline = ""
|
||||
for entry in data:
|
||||
if entry.headline == 1:
|
||||
if len(self.text.strip_html_tags(headline) or []) > limit / 2:
|
||||
continue
|
||||
headline += self.format_entry(entry, receiver)
|
||||
else:
|
||||
if len(self.text.strip_html_tags(normal) or []) > limit / 2:
|
||||
continue
|
||||
normal += self.format_entry(entry, receiver)
|
||||
if len(self.text.strip_html_tags(headline + normal) or []) > limit:
|
||||
normal += f" There seem to be more news,<br> but they're too long to get shown here. " \
|
||||
f"[{self.text.make_tellcmd('Display', 'news detail')}]<br>"
|
||||
return headline + "____________________________<br><br>" + normal if headline != "" else normal
|
||||
|
||||
# noinspection LongLine
|
||||
def format_entry(self, entry, receiver=None, mod=False):
|
||||
name = self.bot.get_char_name().upper()
|
||||
|
||||
base = f"""<font color=#8CB5FF>On {entry.added_at.strftime("%d.%m.%Y - %H:%M:%S")} UTC by <white>{self.bot.character_service.resolve_char_to_name(entry.added_by) if entry.added_by != 0 else f"{name}"}</white> (ID {entry.id}):</font><br><white>{entry.text}</white><br><br>"""
|
||||
if mod:
|
||||
base += f"""<br> - <green>Moderate this entry: [{self.text.make_tellcmd('PIN' if entry.headline == 0 else 'UNPIN', f'news {"pin" if entry.headline == 0 else "unpin"} {entry.id}')}] [{self.text.make_tellcmd('DELETE', f'news delete {entry.id}')}]</green>"""
|
||||
return base
|
||||
|
||||
def add_entry(self, text, sender):
|
||||
self.db.exec("INSERT INTO news(text, added_by, added_at) VALUES(?, ?, ?)",
|
||||
[text, sender.char_id, datetime.utcfromtimestamp(time.time())])
|
||||
@@ -0,0 +1,121 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from core.buddy_service import BuddyService
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.db import DB
|
||||
from core.decorators import instance, command
|
||||
from core.job_scheduler import JobScheduler
|
||||
from core.logger import Logger
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.setting_service import SettingService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.core.accounting.preference_controller import PreferenceController
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
from modules.core.ban.ban_service import BanService
|
||||
from modules.core.discord.discord_controller import DiscordController
|
||||
from modules.onlinebot.online.org_alias_controller import OrgAliasController
|
||||
|
||||
|
||||
@instance()
|
||||
class WeeklyController:
|
||||
# dates = {"ai": [1618704000, 1619395200],
|
||||
# "bs": [1619913600, 1620604800],
|
||||
# "dio": [1621123200, 1621814400],
|
||||
# }
|
||||
dates = {"ai": [1627171200, 1627862400],
|
||||
"bs": [1628380800, 1629072000],
|
||||
"dio": [1629590400, 1630281600],
|
||||
}
|
||||
duration = 60 * 60 * 24 * 42 # 3628800
|
||||
|
||||
def inject(self, registry):
|
||||
self.logger = Logger(__name__)
|
||||
self.bot: Tyrbot = 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.util: Util = registry.get_instance("util")
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
self.pork: PorkService = registry.get_instance("pork_service")
|
||||
self.org_pork: PorkService = registry.get_instance("org_pork_service")
|
||||
self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
|
||||
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.discord: DiscordController = registry.get_instance("discord_controller")
|
||||
self.job_schedule: JobScheduler = registry.get_instance("job_scheduler")
|
||||
self.preferences: PreferenceController = registry.get_instance("preference_controller")
|
||||
self.alias_controller: OrgAliasController = registry.get_instance("org_alias_controller")
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
|
||||
@command(command="icc", params=[], description="ICC Weekly", access_level="member")
|
||||
def show_raids(self, _):
|
||||
events = [self.get_next_bs(),
|
||||
self.get_next_ai(),
|
||||
self.get_next_dio()]
|
||||
|
||||
events = sorted(events, key=lambda event: event.start)
|
||||
current = "None"
|
||||
if events[0].is_running():
|
||||
current = self.get_long_name(events[0].type) + \
|
||||
f' [Ends in {self.util.time_to_readable(events[0].end - time.time())}]'
|
||||
blob = "" \
|
||||
f"Current Mission: {current}\n" \
|
||||
f"\n" \
|
||||
f"Planned:\n"
|
||||
for i in events:
|
||||
blob += self.format_entry(i)
|
||||
return ChatBlob("ICC Weekly Missions", blob)
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def time_to_readable(self, time):
|
||||
return datetime.utcfromtimestamp(time).strftime("%d.%m.%Y")
|
||||
|
||||
def format_entry(self, event):
|
||||
return f"{self.get_long_name(event.type)}: <highlight>{self.time_to_readable(event.start)}</highlight> " \
|
||||
f"-> <highlight>{self.time_to_readable(event.end - 1)}</highlight>\n" if not event.is_running() else ""
|
||||
|
||||
def get_long_name(self, event_type):
|
||||
return {"ai": "Alien Weekly",
|
||||
"bs": "Battlestation Weekly",
|
||||
"dio": "Dust it Off Weekly"}.get(event_type)
|
||||
|
||||
def get_next_event(self, event_type, now):
|
||||
cycle = (now - self.dates[event_type][0]) / self.duration
|
||||
cycle = round(cycle)
|
||||
event = WeeklyEvent(event_type, self.dates[event_type][0] + cycle * self.duration,
|
||||
self.dates[event_type][1] + cycle * self.duration)
|
||||
if event.end <= now:
|
||||
event.start += self.duration
|
||||
event.end += self.duration
|
||||
return event
|
||||
|
||||
def get_next_dio(self, when=0):
|
||||
when = time.time() if when == 0 else when
|
||||
return self.get_next_event("dio", when)
|
||||
|
||||
def get_next_bs(self, when=0):
|
||||
when = time.time() if when == 0 else when
|
||||
return self.get_next_event("bs", when)
|
||||
|
||||
def get_next_ai(self, when=0):
|
||||
when = time.time() if when == 0 else when
|
||||
return self.get_next_event("ai", when)
|
||||
|
||||
|
||||
class WeeklyEvent:
|
||||
start = 0
|
||||
end = 0
|
||||
type = ""
|
||||
|
||||
def __init__(self, event_type, start, end):
|
||||
self.start = start
|
||||
self.end = end
|
||||
self.type = event_type
|
||||
|
||||
def is_running(self, when=0):
|
||||
when = time.time() if when == 0 else when
|
||||
return self.start <= when <= self.end
|
||||
@@ -0,0 +1,172 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
from conf.config import BotConfig
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.decorators import instance, command, event
|
||||
from core.dict_object import DictObject
|
||||
from core.job_scheduler import JobScheduler
|
||||
from core.logger import Logger
|
||||
from core.setting_service import SettingService
|
||||
from core.setting_types import BooleanSettingType
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.standard.datanet.ws_controller import WebsocketRelayController
|
||||
|
||||
|
||||
@instance()
|
||||
class WorldBossController:
|
||||
alerts = [480 * 60, 360 * 60, 240 * 60, 120 * 60, 60 * 60, 60 * 15,
|
||||
60 * 5, 60 * 3, 60 * 2, 60, 30, 15, 10, 5, 4, 3, 2, 1, 0]
|
||||
jobs = []
|
||||
timer_data = []
|
||||
|
||||
def __init__(self):
|
||||
mod = __import__(f'conf.{sys.argv[1]}', fromlist=['BotConfig'])
|
||||
config: BotConfig = getattr(mod, 'BotConfig')
|
||||
if hasattr(config, "timer_url"):
|
||||
self.timer_api = config.timer_url
|
||||
else:
|
||||
self.timer_api = None
|
||||
|
||||
def inject(self, registry):
|
||||
self.logger = Logger(__name__)
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
self.util: Util = registry.get_instance("util")
|
||||
self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
|
||||
self.job_scheduler: JobScheduler = registry.get_instance("job_scheduler")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
|
||||
def pre_start(self):
|
||||
self.setting_service.register_new(self.module_name, 'timer_spam', True, BooleanSettingType(),
|
||||
"should timers be spammed")
|
||||
|
||||
@event(WebsocketRelayController.WS_RELAY, "save most current timers")
|
||||
def get_timer(self, _, data):
|
||||
if data.type == "timer":
|
||||
self.timer_data = data.payload
|
||||
|
||||
def test(test_data):
|
||||
if test_data:
|
||||
for job in self.jobs:
|
||||
if job["name"] == test_data.name:
|
||||
return
|
||||
self.job_scheduler.delayed_job(self.timer_alert, 2, test_data)
|
||||
|
||||
if self.setting_service.get_value("timer_spam") == "1":
|
||||
for row in self.timer_data:
|
||||
data = self.get_spawn(row)
|
||||
test(data)
|
||||
|
||||
def get_spawn(self, timer):
|
||||
timer = DictObject(timer)
|
||||
if timer.name == "Loren Warr":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 15 * 60)
|
||||
elif timer.name == "Tarasque":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 30 * 60)
|
||||
elif timer.name == "The Hollow Reaper":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 15 * 60)
|
||||
elif timer.name == "Vizaresh":
|
||||
data = self.calc_spawn_mortal(timer.time, 17 * 60 * 60, 6 * 60 + 20)
|
||||
else:
|
||||
return None
|
||||
if not data:
|
||||
return
|
||||
if data.spawn < time.time():
|
||||
if data.mortal > time.time():
|
||||
return DictObject(
|
||||
{'name': timer.name, 'type': 'mortal', 'time': data.mortal - time.time(), 'at': data.mortal,
|
||||
'data': data})
|
||||
return DictObject(
|
||||
{'name': timer.name, 'type': 'spawn', 'time': data.spawn - time.time(), 'at': data.spawn, 'data': data})
|
||||
|
||||
def calc_spawn_mortal(self, last, respawn, immortal):
|
||||
pop = last + respawn
|
||||
attackable = pop + immortal
|
||||
now = time.time()
|
||||
|
||||
# Mortal
|
||||
if immortal > attackable - now > 0:
|
||||
return DictObject({'spawn': pop, 'mortal': attackable})
|
||||
elif immortal > attackable + respawn - now > 0:
|
||||
return DictObject({'spawn': pop + respawn, 'mortal': attackable + respawn})
|
||||
|
||||
# Spawn
|
||||
elif respawn > (pop - now) > 0:
|
||||
return DictObject({'spawn': pop, 'mortal': pop})
|
||||
elif respawn > pop + respawn - now > 0:
|
||||
return DictObject({'spawn': attackable + respawn, 'mortal': attackable + respawn + immortal})
|
||||
elif last - now > 0:
|
||||
return DictObject({'spawn': last - immortal, 'mortal': last})
|
||||
|
||||
def send_warn(self, msg):
|
||||
self.bot.send_private_channel_message(f"[<red>WB</red>] {msg}")
|
||||
|
||||
def get_next_alert(self, duration):
|
||||
for alert in self.alerts:
|
||||
if duration - 1 > alert:
|
||||
return duration - alert - 1
|
||||
return duration
|
||||
|
||||
@command(command="gaunt", params=[], description="Displays the next Vizaresh pop time", access_level="member")
|
||||
def show_gaunt(self, _):
|
||||
for timer in self.timer_data:
|
||||
if timer['name'] == "Vizaresh":
|
||||
return self.show_user(timer)
|
||||
return "Timer not found"
|
||||
|
||||
@command(command="loren", params=[], description="Displays the next Loren Warr pop time", access_level="member")
|
||||
def show_loren(self, _):
|
||||
for timer in self.timer_data:
|
||||
if timer['name'] == "Loren Warr":
|
||||
return self.show_user(timer)
|
||||
return "Timer not found"
|
||||
|
||||
@command(command="tara", params=[], description="Displays the next Tara pop time", access_level="member")
|
||||
def show_tara(self, _):
|
||||
for timer in self.timer_data:
|
||||
if timer['name'] == "Tarasque":
|
||||
return self.show_user(timer)
|
||||
return "Timer not found"
|
||||
|
||||
def show_user(self, timer):
|
||||
timer = self.get_spawn(timer)
|
||||
if not timer:
|
||||
return "No timers cached; please try again later."
|
||||
if timer.type == "mortal":
|
||||
return f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time)}"
|
||||
elif timer.type == "spawn":
|
||||
return f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time)}"
|
||||
|
||||
def timer_alert(self, t, timer):
|
||||
if self.setting_service.get_value("timer_spam") == "0":
|
||||
return
|
||||
for row in self.timer_data:
|
||||
if row["name"] == timer.name:
|
||||
timer = self.get_spawn(row)
|
||||
alert_duration = self.get_next_alert(timer.at - t)
|
||||
if timer.at - time.time() < 1:
|
||||
if timer.type == "mortal":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: is now mortal")
|
||||
self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
elif timer.type == "spawn":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: has just spawned")
|
||||
self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
else: # timer.at > time.time():
|
||||
if timer.type == "mortal":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time)}")
|
||||
elif timer.type == "spawn":
|
||||
if alert_duration > 60 * 2:
|
||||
self.send_warn(
|
||||
f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time)}")
|
||||
for row in self.timer_data:
|
||||
if row["name"] == timer.name:
|
||||
timer = self.get_spawn(row)
|
||||
job_id = self.job_scheduler.scheduled_job(self.timer_alert, t + alert_duration, timer)
|
||||
for job in self.jobs:
|
||||
if job['name'] == timer.name:
|
||||
job['id'] = job_id
|
||||
return
|
||||
self.jobs.append({'name': timer.name, 'id': job_id})
|
||||
Reference in New Issue
Block a user