Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,403 @@
|
||||
import re
|
||||
import secrets
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.command_param_types import Const, Int, Any
|
||||
from core.db import DB
|
||||
from core.decorators import instance, command, timerevent
|
||||
from core.setting_service import SettingService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
from modules.raidbot.raid.raidbot_controller import Raider
|
||||
from modules.standard.items.items_controller import ItemsController
|
||||
from modules.standard.loot.item_types import LootItem
|
||||
from modules.standard.raid.leader_controller import LeaderController
|
||||
|
||||
|
||||
@instance()
|
||||
class LootController:
|
||||
NOT_LEADER_MSG = "Error! You must be raid leader, or have higher access " \
|
||||
"level than the raid leader to use this command."
|
||||
|
||||
def __init__(self):
|
||||
self.loot_list = OrderedDict()
|
||||
self.last_modify = None
|
||||
|
||||
def inject(self, registry):
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.db: DB = registry.get_instance("db")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
self.leader_controller: LeaderController = registry.get_instance("leader_controller", is_optional=True)
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.items_controller: ItemsController = registry.get_instance("items_controller")
|
||||
self.raid_controller = None
|
||||
self.raid_controller = registry.get_instance("raidbot_controller", is_optional=True)
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
self.alts_service: AccountService = registry.get_instance("account_service")
|
||||
self.alias: CommandAliasService = registry.get_instance("command_alias_service")
|
||||
|
||||
def pre_start(self):
|
||||
self.db.load_sql_file(self.module_dir + "/raid_loot.sql", pre_optimized=True)
|
||||
self.db.create_view("raid_loot")
|
||||
self.alias.add_alias("add", "loot add")
|
||||
self.alias.add_alias("rem", "loot rem")
|
||||
self.alias.add_alias("remove", "loot remo")
|
||||
self.alias.add_alias("flatroll", "loot roll")
|
||||
self.alias.add_alias("result", "loot roll")
|
||||
self.alias.add_alias("results", "loot roll")
|
||||
self.alias.add_alias("win", "loot roll")
|
||||
|
||||
@command(command="loot", params=[], description="Show the list of added items", access_level="member")
|
||||
def loot_cmd(self, _):
|
||||
if not self.loot_list:
|
||||
return "Loot list is empty."
|
||||
|
||||
return self.get_loot_list()
|
||||
|
||||
@command(command="loot", params=[Const("edit")], description="Show the list of added items", access_level="leader",
|
||||
sub_command="modify")
|
||||
def loot_edit_cmd(self, _, _1):
|
||||
if not self.loot_list:
|
||||
return "Loot list is empty."
|
||||
|
||||
return self.get_loot_list(edit=True)
|
||||
|
||||
@command(command="loot", params=[Const("clear")], description="Clear all loot", access_level="leader",
|
||||
sub_command="modify")
|
||||
def loot_clear_cmd(self, request, _):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if self.loot_list:
|
||||
self.loot_list.clear()
|
||||
self.last_modify = None
|
||||
self.bot.send_private_channel_message("Loot list cleared.")
|
||||
else:
|
||||
return "Loot list is already empty."
|
||||
|
||||
@command(command="loot", params=[Const("remitem"), Int("item_index")],
|
||||
description="Remove an existing loot item", access_level="leader", sub_command="modify")
|
||||
def loot_rem_item_cmd(self, request, _, item_index: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if not self.loot_list:
|
||||
return "Loot list is empty."
|
||||
|
||||
try:
|
||||
if self.loot_list[item_index]:
|
||||
self.last_modify = int(time.time())
|
||||
self.bot.send_private_channel_message(
|
||||
"Removed %s from loot list." % self.loot_list.pop(item_index).get_item_str())
|
||||
else:
|
||||
return "Item error."
|
||||
except KeyError:
|
||||
return "Wrong index given."
|
||||
|
||||
@command(command="loot", params=[Const("increase"), Int("item_index")], description="Increase item count",
|
||||
access_level="leader", sub_command="modify")
|
||||
def loot_increase_item_cmd(self, request, _, item_index: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if not self.loot_list:
|
||||
return "Loot list is empty."
|
||||
|
||||
try:
|
||||
loot_item = self.loot_list[item_index]
|
||||
|
||||
if loot_item:
|
||||
loot_item.count += 1
|
||||
self.last_modify = int(time.time())
|
||||
self.bot.send_private_channel_message(
|
||||
"Increased item count for %s to %d." % (loot_item.get_item_str(), loot_item.count))
|
||||
else:
|
||||
return "Item error."
|
||||
except KeyError:
|
||||
return "Wrong index given."
|
||||
|
||||
@command(command="loot", params=[Const("decrease"), Int("item_index")], description="Decrease item count",
|
||||
access_level="leader", sub_command="modify")
|
||||
def loot_decrease_item_cmd(self, request, _, item_index: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if not self.loot_list:
|
||||
return "Loot list is empty."
|
||||
|
||||
try:
|
||||
loot_item = self.loot_list[item_index]
|
||||
|
||||
if loot_item:
|
||||
loot_item.count = loot_item.count - 1 if loot_item.count > 1 else 1
|
||||
self.last_modify = int(time.time())
|
||||
self.bot.send_private_channel_message(
|
||||
"Decreased item count for %s to %d." % (loot_item.get_item_str(), loot_item.count))
|
||||
else:
|
||||
return "Item error."
|
||||
except KeyError:
|
||||
return "Wrong index given."
|
||||
|
||||
@command(command="loot", params=[Const("add"), Int("item_index")], description="Add yourself to item",
|
||||
access_level="member")
|
||||
def loot_add_to_cmd(self, request, _, item_index: int):
|
||||
main = self.alts_service.get_account(request.sender.char_id)
|
||||
if self.raid_controller:
|
||||
raider: Raider = self.raid_controller.is_in_raid(main.char_id)
|
||||
if type(raider) == Raider:
|
||||
if not raider.is_active:
|
||||
self.bot.send_mass_message(request.sender.char_id,
|
||||
"You are not participating in the raid, and cannot add to the loot.")
|
||||
return
|
||||
elif raider is None:
|
||||
self.bot.send_mass_message(request.sender.char_id,
|
||||
"You are not participating in the raid, and cannot add to the loot.")
|
||||
return
|
||||
try:
|
||||
loot_item = self.loot_list[item_index]
|
||||
old_item = self.is_already_added(request.sender.name)
|
||||
if old_item:
|
||||
if old_item.get_item_str() == loot_item.get_item_str():
|
||||
name = "You have" if request.channel == "msg" else request.sender.name
|
||||
self.bot.send_mass_message(request.sender.char_id,
|
||||
"%s already added to %s." % (name, loot_item.get_item_str()))
|
||||
old_item.bidders.remove(request.sender.name)
|
||||
|
||||
loot_item.bidders.append(request.sender.name)
|
||||
|
||||
self.last_modify = int(time.time())
|
||||
|
||||
if old_item is not None:
|
||||
text = "moved from %s to %s." % (old_item.get_item_str(), loot_item.get_item_str())
|
||||
self.bot.send_mass_message(request.sender.char_id, "You have %s" % text)
|
||||
self.bot.send_private_channel_message(request.sender.name + " " + text)
|
||||
else:
|
||||
text = "added to %s." % loot_item.get_item_str()
|
||||
self.bot.send_mass_message(request.sender.char_id, "You have %s" % text)
|
||||
self.bot.send_private_channel_message(request.sender.name + " " + text)
|
||||
|
||||
except KeyError:
|
||||
return "Wrong index given."
|
||||
|
||||
@command(command="loot", params=[Const("rem")], description="Remove yourself from item", access_level="member")
|
||||
def loot_rem_from_cmd(self, request, _):
|
||||
try:
|
||||
loot_item = self.is_already_added(request.sender.name)
|
||||
|
||||
if loot_item is not None:
|
||||
loot_item.bidders.remove(request.sender.name)
|
||||
|
||||
self.last_modify = int(time.time())
|
||||
text = "removed from %s." % loot_item.get_item_str()
|
||||
self.bot.send_private_message(request.sender.char_id, "You were %s" % text)
|
||||
self.bot.send_private_channel_message(request.sender.name + " was " + text)
|
||||
else:
|
||||
return "You are not added to any loot."
|
||||
except KeyError:
|
||||
return "Wrong index given."
|
||||
|
||||
@command(command="loot", params=[Const("roll")], description="Roll all loot", access_level="leader",
|
||||
sub_command="modify")
|
||||
def loot_roll_cmd(self, request, _):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if self.loot_list:
|
||||
blob = ""
|
||||
remove = []
|
||||
for i, loot_item in self.loot_list.items():
|
||||
winners = []
|
||||
|
||||
if loot_item.bidders:
|
||||
if len(loot_item.bidders) <= loot_item.count:
|
||||
winners = loot_item.bidders.copy()
|
||||
loot_item.count -= len(loot_item.bidders)
|
||||
loot_item.bidders = []
|
||||
else:
|
||||
for j in range(0, loot_item.count):
|
||||
winner = secrets.choice(loot_item.bidders)
|
||||
|
||||
winners.append(winner)
|
||||
loot_item.bidders.remove(winner)
|
||||
loot_item.count = loot_item.count - 1 if loot_item.count > 0 else 0
|
||||
for user in winners:
|
||||
self.account_service.add_log(self.account_service.character_service.resolve_char_to_id(user),
|
||||
"loot",
|
||||
f"{loot_item.get_item_str()}",
|
||||
request.sender.char_id)
|
||||
blob += "%d. %s\n" % (i, loot_item.get_item_str())
|
||||
blob += " | Winners: <red>%s<end>\n\n" % '<end>, <red>'.join(winners)
|
||||
if loot_item.count == 0:
|
||||
remove.append(i)
|
||||
for i in remove:
|
||||
self.loot_list.pop(i)
|
||||
|
||||
msg = ChatBlob("Roll results", blob)
|
||||
msg.page_prefix = "Time is up! "
|
||||
self.bot.send_private_channel_message(msg if len(blob) > 0 else "No one was added to any loot")
|
||||
if self.loot_list:
|
||||
count = 1
|
||||
for key in sorted(list(self.loot_list.keys())):
|
||||
if self.loot_list[key].count <= 0:
|
||||
del self.loot_list[key]
|
||||
else:
|
||||
loot_item = self.loot_list[key]
|
||||
del self.loot_list[key]
|
||||
self.loot_list[count] = loot_item
|
||||
count += 1
|
||||
else:
|
||||
return "No loot to roll."
|
||||
|
||||
@command(command="loot", params=[Const("addraiditem"), Int("raid_item_id"), Int("item_count")],
|
||||
description="Add item from pre-defined raid to loot list", access_level="leader", sub_command="modify")
|
||||
def loot_add_raid_item(self, request, _, raid_item_id: int, item_count: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
sql = "SELECT r.name, r.comment, r.ql, a.lowid AS low_id, a.highid AS high_id FROM aodb a " \
|
||||
"LEFT JOIN raid_loot r ON (a.name = r.name AND a.highql >= r.ql) " \
|
||||
"WHERE r.id = ? LIMIT 1"
|
||||
item = self.db.query_single(sql, [raid_item_id])
|
||||
|
||||
if item:
|
||||
self.add_item_to_loot(item, item.comment, item_count)
|
||||
|
||||
self.bot.send_private_channel_message("Added %s to loot list." % item.name)
|
||||
else:
|
||||
return "Failed to add item with ID %s." % raid_item_id
|
||||
|
||||
@command(command="loot", params=[Const("addraid"), Any("raid"), Any("category")],
|
||||
description="Add all loot from pre-defined raid", access_level="leader", sub_command="modify")
|
||||
def loot_add_raid_loot(self, request, _, raid: str, category: str):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
items = self.db.query(
|
||||
"SELECT r.raid, r.category, r.id, r.ql, r.name, r.comment, r.multiloot, "
|
||||
"a.lowid AS low_id, "
|
||||
"a.highid AS high_id, a.icon "
|
||||
"FROM raid_loot r "
|
||||
"LEFT JOIN aodb a "
|
||||
"ON (r.name = a.name AND r.ql <= a.highql) "
|
||||
"WHERE r.raid = ? AND r.category = ? "
|
||||
"ORDER BY r.name",
|
||||
[raid, category]
|
||||
)
|
||||
|
||||
if items:
|
||||
for item in items:
|
||||
self.add_item_to_loot(item, item.comment, item.multiloot)
|
||||
|
||||
self.bot.send_private_channel_message("%s table was added to loot." % category)
|
||||
else:
|
||||
return "%s does not have any items registered in loot table." % category
|
||||
|
||||
@command(command="loot",
|
||||
params=[Const("additem", is_optional=True), Int("item"), Int("item_count", is_optional=True)],
|
||||
description="Add an item to loot list by item id", access_level="leader", sub_command="modify")
|
||||
def loot_add_item_id_cmd(self, request, _, item_id, item_count: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
|
||||
if item_count is None:
|
||||
item_count = 1
|
||||
|
||||
item = self.items_controller.get_by_item_id(item_id)
|
||||
if not item:
|
||||
return "Could not find item with ID <highlight>%d<end>." % item_id
|
||||
|
||||
self.add_item_to_loot(item, item_count=item_count)
|
||||
|
||||
self.bot.send_private_channel_message("%s was added to loot list." % item.name)
|
||||
|
||||
@command(command="loot",
|
||||
params=[Const("additem", is_optional=True), Any("item"), Int("item_count", is_optional=True)],
|
||||
description="Add an item to loot list", access_level="leader", sub_command="modify")
|
||||
def loot_add_item_cmd(self, request, _, item, item_count: int):
|
||||
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
|
||||
return LeaderController.NOT_LEADER_MSG
|
||||
loot = ""
|
||||
if item_count is None:
|
||||
item_count = 1
|
||||
item = item.replace("'", "'")
|
||||
items = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)", item)
|
||||
if items and item_count == 1:
|
||||
for item in items:
|
||||
item = self.text.make_item(int(item[2]), int(item[3]), int(item[4]), item[5])
|
||||
if loot != "":
|
||||
loot += ", " + item
|
||||
else:
|
||||
loot += item
|
||||
self.add_item_to_loot(item)
|
||||
else:
|
||||
loot += item
|
||||
self.add_item_to_loot(item, item_count=item_count)
|
||||
|
||||
self.bot.send_private_channel_message("<highlight>%s<end> was added to loot list." % loot)
|
||||
|
||||
@timerevent(budatime="1h",
|
||||
description="Periodically check when loot list was last modified, and clear it "
|
||||
"if last modification was done 1+ hours ago")
|
||||
def loot_clear_event(self, _1, _2):
|
||||
if self.loot_list and self.last_modify:
|
||||
if int(time.time()) - self.last_modify > 3600 and self.loot_list:
|
||||
self.last_modify = None
|
||||
self.loot_list = OrderedDict()
|
||||
self.bot.send_org_message("Loot was last modified more than 1 hour ago, list has been cleared.")
|
||||
self.bot.send_private_channel_message(
|
||||
"Loot was last modified more than 1 hour ago, list has been cleared.")
|
||||
|
||||
def is_already_added(self, name: str):
|
||||
for i, loot_item in self.loot_list.items():
|
||||
if name in loot_item.bidders:
|
||||
return loot_item
|
||||
return None
|
||||
|
||||
def add_item_to_loot(self, item, comment=None, item_count=1):
|
||||
existing_item = next((loot_item for x, loot_item in self.loot_list.items() if loot_item.item == item), None)
|
||||
if existing_item:
|
||||
existing_item.count += 1
|
||||
else:
|
||||
# this prevents loot items from being re-numbered when items are removed
|
||||
end_index = list(self.loot_list.keys())[-1] + 1 if len(self.loot_list) > 0 else 1
|
||||
|
||||
self.loot_list[end_index] = LootItem(item, comment, item_count)
|
||||
|
||||
self.last_modify = int(time.time())
|
||||
|
||||
def get_loot_list(self, edit=False):
|
||||
blob = ""
|
||||
remove = self.text.make_chatcmd("Remove from rolls", "/tell <myname> loot rem")
|
||||
blob += f"[{remove}]\n\n"
|
||||
for i, loot_item in self.loot_list.items():
|
||||
bidders = loot_item.bidders
|
||||
img = ""
|
||||
|
||||
if loot_item.get_item_str()[:2] == "<a" and loot_item.get_item_str()[-4:] == "</a>":
|
||||
item = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)",
|
||||
loot_item.get_item_str())
|
||||
imgid = self.db.query_single("SELECT icon from aodb where lowid=? or highid=?",
|
||||
[item[0][2], item[0][3]])
|
||||
if imgid is not None:
|
||||
img = self.text.make_image(imgid.get("icon")) + " - "
|
||||
blob += "%d. %s%s " % (i, img, item[0][0])
|
||||
|
||||
else:
|
||||
blob += "%d. %s " % (i, loot_item.get_item_str())
|
||||
blob += f"x{loot_item.count} [{self.text.make_chatcmd('Add', f'/tell <myname> loot add {i}')}]\n"
|
||||
blob += " └ "
|
||||
if edit:
|
||||
blob += f"<yellow>[ {self.text.make_tellcmd('+1', f'loot increase {i}')} | " \
|
||||
f"{self.text.make_tellcmd('-1', f'loot decrease {i}')} ]" \
|
||||
f"[ {self.text.make_tellcmd('REM', f'loot remitem {i}')} ]</yellow>\n\n"
|
||||
else:
|
||||
if len(bidders) > 0:
|
||||
blob += "<yellow>%s<end>\n\n" % ', '.join(bidders)
|
||||
else:
|
||||
blob += "<yellow>None added<end>\n\n"
|
||||
|
||||
return ChatBlob("Loot (%d)" % len(self.loot_list), blob)
|
||||
Reference in New Issue
Block a user