Commit 4c9aaeab authored by Geovanny's avatar Geovanny

House implementation for discord

parent 085eb6da
...@@ -2,14 +2,17 @@ import asyncio ...@@ -2,14 +2,17 @@ import asyncio
import discord import discord
import discord import discord
from requests import Session from requests import Session
from discord.ext import commands from discord.ext import commands
from unit.manager import UnitManager from unit.manager import UnitManager
from user.manager import UserManager from user.manager import UserManager
from house.manager import HouseManager
from house.membership.manager import MembershipManager
from house.war.manager import WarManager
from util.command_error_handler import CommandErrorHandler from util.command_error_handler import CommandErrorHandler
from util.help import EditedMinimalHelpCommand, PaginatedHelpCommand from util.help import EditedMinimalHelpCommand, PaginatedHelpCommand
from util.api_requests import Api from util.api_requests import Api
from settings import DISCORD_TOKEN from settings import DISCORD_TOKEN
class ConqBot(commands.Bot): class ConqBot(commands.Bot):
...@@ -45,6 +48,9 @@ bot = ConqBot(command_prefix='>') ...@@ -45,6 +48,9 @@ bot = ConqBot(command_prefix='>')
bot.add_cog(CommandErrorHandler(bot)) bot.add_cog(CommandErrorHandler(bot))
bot.add_cog(UserManager(bot)) bot.add_cog(UserManager(bot))
bot.add_cog(UnitManager(bot)) bot.add_cog(UnitManager(bot))
bot.add_cog(HouseManager(bot))
bot.add_cog(MembershipManager(bot))
bot.add_cog(WarManager(bot))
@bot.event @bot.event
async def on_ready(): async def on_ready():
......
from discord_argparse import *
create_params = ArgumentConverter(
name = RequiredArgument(
str,
doc='House Name',
),
level = OptionalArgument(
int,
doc='House Level',
),
camp_location = OptionalArgument(
str,
doc='Camp Location'
)
)
mod_params = ArgumentConverter(
name = OptionalArgument(
str,
doc='House Name',
),
level = OptionalArgument(
int,
doc='House Level',
),
camp_location = OptionalArgument(
str,
doc='Camp Location'
)
)
\ No newline at end of file
import discord
from discord.ext import commands
from util.pager import Pager
class HousesPager(Pager):
commands_per_page = 8
indent = 3
def add_page(self, cog_name, cog_desc, cmds):
'''Will split into several pages to accomodate the per_page limit.'''
# will obviously not run if no commands are in the page
for cmds_slice in [cmds[i:i + self.commands_per_page] for i in range(0, len(cmds), self.commands_per_page)]:
self.entries.append((cog_name, cog_desc, cmds_slice))
async def craft_page(self, e, page, entries):
cog_name, cog_desc, commands = entries[0]
name = 'Houses'
self.embed.set_author(name=name, icon_url=self.bot.user.avatar_url)
self.embed.description = cog_desc
for name, value in commands:
self.embed.add_field(name=name, value=value, inline=False)
async def craft_page_detail(self, cog_name, cog_desc, command):
name = f'{cog_name} Commands'
embed = discord.Embed()
embed.set_author(name=name, icon_url=self.bot.user.avatar_url)
embed.description = cog_desc
embed.add_field(name=command.name, value=command.help, inline=False)
for name, param in command.clean_params.items():
if isinstance(param.annotation, da.ArgumentConverter):
arguments = param.annotation.arguments
if not arguments:
continue
max_size = max(len(name) for name in arguments)
params_text = ''
for name, argument in arguments.items():
entry = "{0}{1:<{width}} |\t {2}".format(self.indent * " ", name, argument.doc, width=max_size)
params_text += "{0}\n".format(entry)
embed.add_field(name="Arguments", value=params_text)
return embed
async def help_embed(self, e):
e.set_author(name='How do I use the bot?', icon_url=self.bot.user.avatar_url)
e.description = (
'Invoke a command by sending the prefix followed by a command name.\n\n'
'For example, the command signature `track <query>` can be invoked by doing `track yellow`\n\n'
'The different argument brackets mean:'
)
e.add_field(name='<argument>', value='the argument is required.', inline=False)
e.add_field(name='[argument]', value='the argument is optional.\n\u200b', inline=False)
class PaginatedHelpCommand(commands.HelpCommand):
'''Cog that implements the help command and help pager.'''
async def add_command(self, cmds, command, force=False):
if command.hidden:
return
if force is False:
try:
if not await command.can_run(self.context):
return
except commands.CheckFailure:
return
help_message = command.brief or command.help
if help_message is None:
help_message = 'No description available.'
else:
help_message = help_message.split('\n')[0]
cmds.append((self.context.prefix + get_signature(command), help_message))
async def prepare_help_command(self, ctx, command=None):
self.context = ctx
self.pager = HelpPager(ctx, list(), per_page=1)
async def add_cog(self, cog):
cog_name = cog.__class__.__name__
cog_desc = cog.__doc__
cmds = []
added = []
for command in cog.walk_commands():
if command in added:
continue
await self.add_command(cmds, command)
added.append(command)
self.pager.add_page(cog_name, cog_desc, cmds)
async def send_bot_help(self, mapping):
for cog in mapping:
if cog is not None:
await self.add_cog(cog)
await self.pager.go()
async def send_cog_help(self, cog):
await self.add_cog(cog)
await self.pager.go()
async def send_group_help(self, group):
if group.cog_name.lower() == group.name.lower():
await self.send_cog_help(group.cog)
return
added = []
cmds = []
for command in group.walk_commands():
if command in added:
continue
await self.add_command(cmds, command)
added.append(command)
self.pager.add_page(group.cog_name, group.cog.__doc__, cmds)
await self.pager.go()
async def send_command_help(self, command):
cog_name = command.cog_name
if cog_name is not None and cog_name.lower() == command.name:
await self.send_cog_help(command.cog)
return
cog_desc = command.cog.__doc__
embed = await self.pager.craft_page_detail(cog_name, cog_desc, command)
return await self.context.send(embed=embed)
async def command_not_found(self, string):
return commands.CommandNotFound(string)
async def send_error_message(self, error):
if not isinstance(error, commands.CommandNotFound):
return
cmd = str(error)
for cog in self.context.bot.cogs:
if cmd == cog.lower():
await self.send_cog_help(self.context.bot.get_cog(cog))
return
await self.context.send('Command \'{}\' not found.'.format(cmd))
class EditedMinimalHelpCommand(commands.MinimalHelpCommand):
def get_ending_note(self):
return (
'The interactive help menu did not get sent because the bot is missing '
'the following permissions: ' + ', '.join(self.missing_perms)
)
async def send_error_message(self, error):
return
# rip is just the signature command ripped from the lib, but with alias support removed.
def get_signature(command):
"""Returns a POSIX-like signature useful for help command output."""
result = []
parent = command.full_parent_name
name = command.name if not parent else parent + ' ' + command.name
result.append(name)
if command.usage:
result.append(command.usage)
return ' '.join(result)
params = command.clean_params
if not params:
return ' '.join(result)
for name, param in params.items():
if param.default is not param.empty:
# We don't want None or '' to trigger the [name=value] case and instead it should
# do [name] since [name=None] or [name=] are not exactly useful for the user.
should_print = param.default if isinstance(param.default, str) else param.default is not None
if should_print:
result.append('[%s=%s]' % (name, param.default))
else:
result.append('[%s]' % name)
elif param.kind == param.VAR_POSITIONAL:
result.append('[%s...]' % name)
else:
result.append('<%s>' % name)
return ' '.join(result)
\ No newline at end of file
import asyncio
import discord
import json
from discord.ext import commands
from house.model import HouseModel
from util.api_requests import Api, ApiError
from util.embed_style import EmbedStyle
from .h_params import *
class HouseManager(commands.Cog):
def __init__(self, bot, loop=None):
self.bot = bot
self.loop = loop or asyncio.get_event_loop()
def createModels(self, data):
models = []
for item in data:
models.append(HouseModel(**item))
return models
@commands.command()
async def allHouses(self, ctx):
"""Get all Houses"""
try:
data = await Api.get('/house/all');
house_models = self.createModels(data)
return await EmbedStyle.createPages(self.bot, ctx, house_models, 10, self.craftHousesPage);
except ApiError as error:
ctx.send(error.message)
def craftHousesPage(self, data, minI, maxI):
embed = discord.Embed(color=0x19212d)
embed.set_author(name='Conquy')
houses_str = '';
for i in range(minI, maxI):
if i < len(data):
house = data[i]
houses_str+= '[{0}] {1}\t| {2}\t| {3}\t| {4}\n'.format(house.id, house.name, house.level, house.camp_location, house.liege)
embed.add_field(name='id\t| Name\t| Level\t| Camp Location\t| Liege', value=houses_str)
return embed
@commands.command()
async def createHouse(self, ctx, *, params:create_params=create_params.defaults()):
"""Create a house"""
try:
body = params
body['house_name'] = params['name']
body['house_level'] = params.get('level')
session = await self.bot.getUserSession(ctx.message.author)
await Api.postSession('/house', body, session)
await ctx.send('House created')
except ApiError as error:
await ctx.send(error.message)
@commands.command()
async def modHouse(self, ctx, *, params:mod_params=mod_params.defaults()):
"""Modify your house"""
try:
body = params
body['house_name'] = params.get('name')
body['house_level'] = params.get('level')
session = await self.bot.getUserSession(ctx.message.author)
await Api.putSession('/house', body, session)
await ctx.send('House modified')
except ApiError as error:
await ctx.send(error.message)
@commands.command()
async def deleteHouse(self, ctx):
"""Delete your house"""
try:
session = await self.bot.getUserSession(ctx.message.author)
await Api.deleteSession('/house', session)
await ctx.send('House deleted')
except ApiError as error:
await ctx.send(error.message)
\ No newline at end of file
import asyncio
import discord
import json
from discord.ext import commands
from util.api_requests import Api, ApiError
from util.embed_style import EmbedStyle
class MembershipManager(commands.Cog):
def __init__(self, bot, loop=None):
self.bot = bot
self.loop = loop or asyncio.get_event_loop()
@commands.command()
async def sendRequest(self, ctx, house_id:int):
"""Send member request to house id"""
try:
session = await self.bot.getUserSession(ctx.message.author)
await Api.postSession('/house/request', {"house_id": house_id}, session)
await ctx.send('Request sent');
except ApiError as error:
await ctx.send(error.message)
@commands.command()
async def cancelRequest(self, ctx):
"""Cancel member request"""
try:
session = await self.bot.getUserSession(ctx.message.author)
await Api.deleteSession('/house/request', session)
await ctx.send('Request cancelled');
except ApiError as error:
await ctx.send(error.message)
@commands.command()
async def allRequests(self, ctx):
"""All requests to house"""
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/house/requests', session)
if(len(data) == 0):
await ctx.send('No requests')
else:
await EmbedStyle.createPages(self.bot, ctx, data, 10, self.craftRequestsPage)
except ApiError as error:
await ctx.send(error.message)
def craftRequestsPage(self, data, minI, maxI):
embed = discord.Embed(color=0x19212d)
embed.set_author(name='Conquy')
requests_str = '';
for i in range(minI, maxI):
if i < len(data):
request = data[i]
requests_str+= '[{0}] {1}'.format(request.get('id'), request.get('username'))
embed.add_field(name='id\t| Name', value=requests_str)
return embed
@commands.command()
async def acceptRequest(self, ctx, user_id:int):
"""Accept membership request"""
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.postSession('/house/accept-request',{"user_id": user_id} , session)
await ctx.send('Membership accepted')
except ApiError as error:
await ctx.send(error.message)
@commands.command()
async def rejectRequest(self, ctx, user_id:int):
"""Refuse membership request"""
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.deleteSession('/house/reject-request/{0}'.format(user_id), session)
await ctx.send('Membership rejected')
except ApiError as error:
await ctx.send(error.message)
\ No newline at end of file
class HouseModel(object):
def __init__(self, id, house_name, house_level, camp_location, liege_id, liege_username):
self.id = id
self.name = house_name
self.level = house_level
self.camp_location = camp_location
self.liege_id = liege_id
self.liege = liege_username
import asyncio
import discord
import json
from tabulate import tabulate
from datetime import datetime
from dateutil import parser
from discord.ext import commands
from util.api_requests import Api, ApiError
from util.embed_style import EmbedStyle
class WarManager(commands.Cog):
def __init__(self, bot, loop=None):
self.bot = bot
self.loop = loop or asyncio.get_event_loop()
@commands.command()
async def currentWar(self, ctx):
"""Get current war information"""
try:
data = await Api.get('/house/current-war');
date = parser.parse(data.get('day'))
await ctx.send('Current War Date: {0}/{1}/{2}'.format(date.year, date.month, date.day))
except ApiError as error:
await ctx.send(error.message)
async def warParticipation(self, ctx, decision):
try:
session = await self.bot.getUserSession(ctx.message.author)
await Api.postSession('/house/participation', {"decision": decision}, session)
await ctx.send('Participation updated')
except ApiError as error:
await ctx.send(error.message)
@commands.command(aliases=["si"])
async def warYes(self, ctx):
"""Yes confirmation to current war"""
await self.warParticipation(ctx, "Yes")
@commands.command(aliases=["no"])
async def warNo(self, ctx):
"""No confirmation to current war"""
await self.warParticipation(ctx, "No")
@commands.command(aliases=["idk"])
async def warIdk(self, ctx):
"""Maybe confirmation to current war"""
await self.warParticipation(ctx, "Maybe")
@commands.command()
async def houseParticipation(self, ctx):
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/house/participation', session)
date = parser.parse(data['war'].get('day'))
await ctx.send('Participation for War: {0}/{1}/{2}'.format(date.year, date.month, date.day))
await EmbedStyle.createPages(self.bot, ctx, data.get('participation'), 10, self.craftParticipationPage)
except ApiError as error:
await ctx.send(error.message)
def craftParticipationPage(self, data, minI, maxI):
embed = discord.Embed(color=0x19212d)
embed.set_author(name='Conquy')
table = []
for i in range(minI, maxI):
if i < len(data):
part = data[i]
item = part.values()
table.append(item)
headers = ["Name", "Decision"]
max_lens = [len(str(max(i, key=lambda x: len(str(x))))) for i in zip(headers, *table)]
participation_str = '```';
for row in (headers, *table):
participation_str += (' | '.join('{0:{width}}'.format(x, width=y) for x, y in zip(row, max_lens))) + '\n'
participation_str +='```'
embed.add_field(name='Participation', value=participation_str)
return embed
\ No newline at end of file
...@@ -2,4 +2,6 @@ discord.py ...@@ -2,4 +2,6 @@ discord.py
python-dotenv python-dotenv
requests requests
pycryptodome pycryptodome
discord-argparse==1.0.0 discord-argparse==1.0.0
\ No newline at end of file python-dateutil
tabulate
\ No newline at end of file
...@@ -119,11 +119,11 @@ class UnitManager(commands.Cog): ...@@ -119,11 +119,11 @@ class UnitManager(commands.Cog):
"""Gets all units""" """Gets all units"""
data = await Api.get('/unit/all') data = await Api.get('/unit/all')
if(data==None or len(data['units'])==0): if(data==None or len(data)==0):
return await ctx.send('No units found') return await ctx.send('No units found')
units_data = [] units_data = []
for item in data['units']: for item in data:
units_data.append(Unit(**item)) units_data.append(Unit(**item))
await self.createUnitTable(ctx, units_data) await self.createUnitTable(ctx, units_data)
......
import asyncio import asyncio
import discord import discord
import json import json
from discord.ext import commands import random
from discord.user import User import string
from unit.model import Unit from discord.ext import commands
from util.api_requests import Api, ApiError from discord.user import User
from util.embed_style import EmbedStyle from unit.model import Unit
from .uu_parameters import * from util.api_requests import Api, ApiError
from util.embed_style import EmbedStyle
from .uu_parameters import *
class UserManager(commands.Cog): class UserManager(commands.Cog):
...@@ -18,14 +20,26 @@ class UserManager(commands.Cog): ...@@ -18,14 +20,26 @@ class UserManager(commands.Cog):
async def handleApiError(self, ctx, error): async def handleApiError(self, ctx, error):
return await ctx.send(error.message) return await ctx.send(error.message)
def randomPassword(self, stringLength=10):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
@commands.command() @commands.command()
async def registerUser(self, ctx): async def registerUser(self, ctx, *, params:register_params=register_params.defaults()):
"""Register user. Only done once per user. Can't access user related content otherwise""" """Register user. Only done once per user. Can't access user related content otherwise.
req_body = {'discordId': ctx.message.author.id} Username is optional and the discord username is default. Password is random if not specified"""
username = params.get('username')
user = ctx.message.author;
if(username==None):
username = user.name
password = params.get('password')
if(password==None):
password = self.randomPassword(random.randint(8, 16))
req_body = {'discordId': ctx.message.author.id, 'username': username, 'password': password}
try: try:
await Api.post('/user/discord-register', req_body) await Api.post('/user/discord-register', req_body)
await ctx.send('Register succesful') await user.send('Register succesful\nUsername: {0}\nPassword: {1}'.format(username, password))
except ApiError as error: except ApiError as error:
return await self.handleApiError(ctx, error) return await self.handleApiError(ctx, error)
...@@ -126,7 +140,7 @@ class UserManager(commands.Cog): ...@@ -126,7 +140,7 @@ class UserManager(commands.Cog):
session = await self.bot.getUserSession(ctx.message.author) session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/user/units', session) data = await Api.getSession('/user/units', session)
units_data = [] units_data = []
for item in data['units']: for item in data:
units_data.append(Unit(**item)) units_data.append(Unit(**item))
return await EmbedStyle.createPages(self.bot, ctx, units_data, 5, self.createUnitPage) return await EmbedStyle.createPages(self.bot, ctx, units_data, 5, self.createUnitPage)
except ApiError as error: except ApiError as error:
......
...@@ -9,4 +9,15 @@ param_converter = ArgumentConverter( ...@@ -9,4 +9,15 @@ param_converter = ArgumentConverter(
bool, bool,
doc='Is Unit Elite', doc='Is Unit Elite',
) )
)
register_params = ArgumentConverter(
username = OptionalArgument(
str,
doc='Username for web app',
),
password = OptionalArgument(
str,
doc='Password for web app',
)
) )
\ No newline at end of file
...@@ -5,6 +5,8 @@ class EmbedStyle: ...@@ -5,6 +5,8 @@ class EmbedStyle:
@staticmethod @staticmethod
async def createPages(bot, ctx, data, max_rows, createRowsFunc): async def createPages(bot, ctx, data, max_rows, createRowsFunc):
if(len(data) == 0):
return await ctx.send('No data')
max_pages = len(data) // max_rows max_pages = len(data) // max_rows
rem = len(data) % max_rows rem = len(data) % max_rows
cur_page = 0; cur_page = 0;
...@@ -16,7 +18,6 @@ class EmbedStyle: ...@@ -16,7 +18,6 @@ class EmbedStyle:
while True: while True:
if first_run: if first_run:
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows) embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
first_run = False first_run = False
msg = await ctx.send(embed=embed) msg = await ctx.send(embed=embed)
...@@ -45,19 +46,34 @@ class EmbedStyle: ...@@ -45,19 +46,34 @@ class EmbedStyle:
try: try:
res, user = await bot.wait_for('reaction_add', timeout=30.0, check=check_react) res, user = await bot.wait_for('reaction_add', timeout=30.0, check=check_react)
except TimeoutError: except TimeoutError:
return await msg.clear_reactions() return await EmbedStyle.pagesTimeout(msg)
if '⏪' in str(res.emoji): if '⏪' in str(res.emoji):
cur_page-= 1 cur_page-= 1
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows) embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions() msg = await EmbedStyle.changePage(ctx, msg, embed)
await msg.edit(embed=embed)
if '⏩' in str(res.emoji): if '⏩' in str(res.emoji):
cur_page+= 1 cur_page+= 1
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows) embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions() msg = await EmbedStyle.changePage(ctx, msg, embed)
await msg.edit(embed=embed)
\ No newline at end of file @staticmethod
async def pagesTimeout(msg):
if isinstance(msg.channel, discord.channel.DMChannel):
return await msg.delete();
else:
return await msg.clear_reactions();
@staticmethod
async def changePage(ctx, msg, embed):
if isinstance(msg.channel, discord.channel.DMChannel):
await msg.delete();
return await ctx.send(embed=embed)
else:
await msg.clear_reactions();
await msg.edit(embed=embed)
return msg
...@@ -4,6 +4,14 @@ const model = {}; ...@@ -4,6 +4,14 @@ const model = {};
const h_columns = ['house_name', 'house_level', 'camp_location']; const h_columns = ['house_name', 'house_level', 'camp_location'];
async function checkHouseRequest(house_id, user_id){
const sql_exists = 'SELECT EXISTS(SELECT * FROM house_requests WHERE house_id = ? AND user_id = ?) as result;'
const exists = await db.con.query(sql_exists, [house_id , user_id]);
if(exists[0] && exists[0].result===0){
throw Error("Membership request not send for user's house")
}
}
model.getAll = async () => { model.getAll = async () => {
const sql_text = `SELECT h.*, u.username as liege_username const sql_text = `SELECT h.*, u.username as liege_username
FROM houses as h FROM houses as h
...@@ -30,7 +38,7 @@ model.insertHouse = async(body, liege_id) => { ...@@ -30,7 +38,7 @@ model.insertHouse = async(body, liege_id) => {
if(body){ if(body){
for (let i = 0; i < h_columns.length; i++) { for (let i = 0; i < h_columns.length; i++) {
const element = h_columns[i]; const element = h_columns[i];
if(body[element]!==undefined){ if(body[element]!==undefined && body[element]!==null){
column_text += ', ' + element; column_text += ', ' + element;
value_text += ', ' + db.con.escape(body[element]); value_text += ', ' + db.con.escape(body[element]);
} }
...@@ -59,7 +67,7 @@ model.modifyHouse = async(house_id, body) => { ...@@ -59,7 +67,7 @@ model.modifyHouse = async(house_id, body) => {
for (let i = 0; i < h_columns.length; i++) { for (let i = 0; i < h_columns.length; i++) {
const element = h_columns[i]; const element = h_columns[i];
if(body[element]!==undefined){ if(body[element]!==undefined && body[element]!==null){
if(set_text===''){ if(set_text===''){
set_text += `${element} = ${db.con.escape(body[element])}`; set_text += `${element} = ${db.con.escape(body[element])}`;
}else{ }else{
...@@ -116,6 +124,7 @@ model.getHouseRequests = async(house_id) => { ...@@ -116,6 +124,7 @@ model.getHouseRequests = async(house_id) => {
} }
model.acceptRequest = async(user_id, house_id) => { model.acceptRequest = async(user_id, house_id) => {
checkHouseRequest(house_id, user_id);
const sql_text = 'DELETE FROM house_requests WHERE user_id = ?;'; const sql_text = 'DELETE FROM house_requests WHERE user_id = ?;';
const sql_text2 = 'UPDATE users SET house_id = ?, lk_house_role = \'kng\' WHERE id = ?;'; const sql_text2 = 'UPDATE users SET house_id = ?, lk_house_role = \'kng\' WHERE id = ?;';
...@@ -127,7 +136,9 @@ model.acceptRequest = async(user_id, house_id) => { ...@@ -127,7 +136,9 @@ model.acceptRequest = async(user_id, house_id) => {
await db.con.query('COMMIT;'); await db.con.query('COMMIT;');
} }
model.rejectRequest = async(user_id) => { model.rejectRequest = async(user_id, house_id) => {
checkHouseRequest(house_id, user_id);
const sql_text = 'DELETE FROM house_requests WHERE user_id = ?;'; const sql_text = 'DELETE FROM house_requests WHERE user_id = ?;';
await db.con.query(sql_text, [user_id]); await db.con.query(sql_text, [user_id]);
......
...@@ -182,14 +182,12 @@ authRouter.get('/requests', async (context, next) => { ...@@ -182,14 +182,12 @@ authRouter.get('/requests', async (context, next) => {
}); });
authRouter.post('/accept-request', async (context, next) => { authRouter.post('/accept-request', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.sen); checkPermissions(context, HOUSE_ROLES.sen);
try{ try{
const body = context.request.body; const body = context.request.body;
if(!body || !body.user_id){ if(!body || !body.user_id){
throw Error("No user to accept"); throw Error("No user to accept");
} }
console.log(body.user_id);
await houseModel.acceptRequest(body.user_id, context.user.house_id); await houseModel.acceptRequest(body.user_id, context.user.house_id);
context.response.status = 204; context.response.status = 204;
}catch(error){ }catch(error){
...@@ -199,14 +197,13 @@ authRouter.post('/accept-request', async (context, next) => { ...@@ -199,14 +197,13 @@ authRouter.post('/accept-request', async (context, next) => {
}); });
authRouter.delete('/reject-request/:user_id', async (context, next) => { authRouter.delete('/reject-request/:user_id', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.sen); checkPermissions(context, HOUSE_ROLES.sen);
try{ try{
const body = context.request.body; const body = context.request.body;
if(!context.params.user_id){ if(!context.params.user_id){
throw Error("No user to refuse"); throw Error("No user to refuse");
} }
await houseModel.rejectRequest(context.params.user_id); await houseModel.rejectRequest(context.params.user_id, context.user.house_id);
context.response.status = 204; context.response.status = 204;
}catch(error){ }catch(error){
console.log(error); console.log(error);
...@@ -288,17 +285,13 @@ authRouter.post('/', async (context, next) => { ...@@ -288,17 +285,13 @@ authRouter.post('/', async (context, next) => {
} }
}); });
authRouter.put('/:house_id', async (context, next) => { authRouter.put('/', async (context, next) => {
console.log('asd')
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.LIEGE) checkPermissions(context, HOUSE_ROLES.LIEGE)
try{ try{
console.log('dsa')
const body = context.request.body; const body = context.request.body;
if(!body){ if(!body){
throw Error('No params') throw Error('No params')
} }
console.log(body)
await houseModel.modifyHouse(context.user.house_id, body); await houseModel.modifyHouse(context.user.house_id, body);
context.response.status = 204; context.response.status = 204;
}catch(error){ }catch(error){
...@@ -307,11 +300,10 @@ authRouter.put('/:house_id', async (context, next) => { ...@@ -307,11 +300,10 @@ authRouter.put('/:house_id', async (context, next) => {
} }
}); });
authRouter.delete('/:house_id', async (context, next) => { authRouter.delete('/', async (context, next) => {
checkHouse(context);
checkPermissions(context, HOUSE_ROLES.LIEGE); checkPermissions(context, HOUSE_ROLES.LIEGE);
try{ try{
await houseModel.deleteHouse(context.params.house_id, context.user.id); await houseModel.deleteHouse(context.user.house_id, context.user.id);
context.response.status = 204; context.response.status = 204;
}catch(error){ }catch(error){
console.log(error); console.log(error);
...@@ -322,9 +314,13 @@ authRouter.delete('/:house_id', async (context, next) => { ...@@ -322,9 +314,13 @@ authRouter.delete('/:house_id', async (context, next) => {
authRouter.get('/participation', async (context, next) => { authRouter.get('/participation', async (context, next) => {
hasHouse(context); hasHouse(context);
try{ try{
const data = await houseModel.getParticipation(context.user.house_id); const war = await houseModel.getCurrentWar();
if(!war){
throw Error('Failed to get Current War');
}
const participation = await houseModel.getParticipation(context.user.house_id);
context.response.status = 200; context.response.status = 200;
context.response.body = data; context.response.body = {war: war, participation: participation};
}catch(error){ }catch(error){
console.log(error); console.log(error);
context.throw('Failed to get Participation'); context.throw('Failed to get Participation');
......
...@@ -59,7 +59,7 @@ async function main(){ ...@@ -59,7 +59,7 @@ async function main(){
app.use(authRouter.routes()).use(authRouter.allowedMethods()); app.use(authRouter.routes()).use(authRouter.allowedMethods());
app.listen(3000, () => console.log('Server Started')); app.listen(process.env.SEV_PORT ? process.env.SEV_PORT : 3000, () => console.log('Server Started'));
} }
......
require('dotenv').config() env_path = process.cwd() + '/.env'
require('dotenv').config(env_path)
SETTINGS = process.env; SETTINGS = process.env;
module.exports = SETTINGS; module.exports = SETTINGS;
\ No newline at end of file
...@@ -59,7 +59,7 @@ unitModel.modifyUnit = async (id, body) => { ...@@ -59,7 +59,7 @@ unitModel.modifyUnit = async (id, body) => {
for (let i = 0; i < unit_columns.length; i++) { for (let i = 0; i < unit_columns.length; i++) {
const element = unit_columns[i]; const element = unit_columns[i];
if(body[element]!==undefined){ if(body[element]!==undefined && body[element]!==null){
if(set_text===''){ if(set_text===''){
set_text += `${element} = ${db.con.escape(body[element])}`; set_text += `${element} = ${db.con.escape(body[element])}`;
}else{ }else{
......
...@@ -6,10 +6,9 @@ const Router = require('@koa/router'); ...@@ -6,10 +6,9 @@ const Router = require('@koa/router');
const router = new Router(); const router = new Router();
const unitModel = require('./model'); const unitModel = require('./model');
router.get('/all', async (context, next) =>{ router.get('/all', async (context, next) =>{
const sql_text = 'SELECT * FROM units ORDER BY name ASC;';
try{ try{
const data = await unitModel.getAll(); const data = await unitModel.getAll();
context.response.body = {units: data}; context.response.body = data;
}catch(error){ }catch(error){
console.log(error); console.log(error);
context.throw(500, 'Server Error'); context.throw(500, 'Server Error');
......
...@@ -104,7 +104,7 @@ userModel.assignUserUnit = async(id, unit_id, body) =>{ ...@@ -104,7 +104,7 @@ userModel.assignUserUnit = async(id, unit_id, body) =>{
if(body){ if(body){
for (let i = 0; i < uu_columns.length; i++) { for (let i = 0; i < uu_columns.length; i++) {
const element = uu_columns[i]; const element = uu_columns[i];
if(body[element]!==undefined){ if(body[element]!==undefined && body[element]!==null){
column_text += ', ' + element; column_text += ', ' + element;
value_text += ', ' + db.con.escape(body[element]); value_text += ', ' + db.con.escape(body[element]);
} }
...@@ -120,7 +120,7 @@ userModel.modifyUserUnit = async(id, unit_id, body) =>{ ...@@ -120,7 +120,7 @@ userModel.modifyUserUnit = async(id, unit_id, body) =>{
for (let i = 0; i < uu_columns.length; i++) { for (let i = 0; i < uu_columns.length; i++) {
const element = uu_columns[i]; const element = uu_columns[i];
if(body[element]!==undefined){ if(body[element]!==undefined && body[element]!==null){
if(set_text===''){ if(set_text===''){
set_text += `${element} = ${db.con.escape(body[element])}`; set_text += `${element} = ${db.con.escape(body[element])}`;
}else{ }else{
...@@ -147,14 +147,14 @@ userModel.addDiscordIdToUser = async (user_id, discord_id) =>{ ...@@ -147,14 +147,14 @@ userModel.addDiscordIdToUser = async (user_id, discord_id) =>{
const data = await db.con.query(sql_text, [discordId, user_id]) const data = await db.con.query(sql_text, [discordId, user_id])
} }
userModel.createUserWithDiscord = async (discord_id) =>{ userModel.createUserWithDiscord = async (discord_id, username, password) =>{
const sql_text = 'INSERT INTO users (discord_id) VALUES (?);'; const hashPassword = await crypto.hash(password);
await db.con.query(sql_text, [discord_id]); const sql_text = 'INSERT INTO users (discord_id, username, password) VALUES (?, ?, ?);';
await db.con.query(sql_text, [discord_id, username, hashPassword]);
} }
userModel.registerUser = async (username, password) =>{ userModel.registerUser = async (username, password) =>{
const hashPassword = await crypto.hash(password); const hashPassword = await crypto.hash(password);
console.log(username, hashPassword)
const sql_text = 'INSERT INTO users (username, password) VALUES (?, ?)'; const sql_text = 'INSERT INTO users (username, password) VALUES (?, ?)';
await db.con.query(sql_text, [username, hashPassword]) await db.con.query(sql_text, [username, hashPassword])
......
...@@ -77,6 +77,7 @@ router.post('/discord-register', async(context, next) =>{ ...@@ -77,6 +77,7 @@ router.post('/discord-register', async(context, next) =>{
try{ try{
await userModel.addDiscordIdToUser(context.user.id, discord_id); await userModel.addDiscordIdToUser(context.user.id, discord_id);
context.status = 204; context.status = 204;
return;
}catch(error){ }catch(error){
console.log(error); console.log(error);
context.throw(422, 'Invalid Discord Id') context.throw(422, 'Invalid Discord Id')
...@@ -91,8 +92,11 @@ router.post('/discord-register', async(context, next) =>{ ...@@ -91,8 +92,11 @@ router.post('/discord-register', async(context, next) =>{
context.throw(422, 'Invalid Discord Id') context.throw(422, 'Invalid Discord Id')
} }
if(!user){ if(!user){
if(!body.username || !body.password){
context.throw(422, 'Missing parameters')
}
try{ try{
await userModel.createUserWithDiscord(discord_id); await userModel.createUserWithDiscord(discord_id, body.username, body.password);
context.status = 204; context.status = 204;
}catch(error){ }catch(error){
context.throw(422, 'Failed to create user with Discord Id') context.throw(422, 'Failed to create user with Discord Id')
...@@ -108,7 +112,7 @@ authRouter.get('/units', async (context, next) => { ...@@ -108,7 +112,7 @@ authRouter.get('/units', async (context, next) => {
if(data.length===1 && data[0].id===null){ if(data.length===1 && data[0].id===null){
throw Error('No Units Found') throw Error('No Units Found')
} }
context.response.body = {units: data}; context.response.body = data;
context.status = 200; context.status = 200;
}catch(error){ }catch(error){
console.log(error) console.log(error)
...@@ -122,7 +126,7 @@ authRouter.get('/units-inverse', async (context, next) => { ...@@ -122,7 +126,7 @@ authRouter.get('/units-inverse', async (context, next) => {
if(data.length===1 && data[0].id===null){ if(data.length===1 && data[0].id===null){
throw Error('No Units Found') throw Error('No Units Found')
} }
context.response.body = {units: data}; context.response.body = data;
context.status = 200; context.status = 200;
}catch(error){ }catch(error){
console.log(error) console.log(error)
......
...@@ -5,7 +5,7 @@ class HouseView extends EventTarget{ ...@@ -5,7 +5,7 @@ class HouseView extends EventTarget{
this.element = element; this.element = element;
this.is_editing = false; this.is_editing = false;
this.modify_btn = this.element.querySelector('#modify_btn'); this.modify_btn = this.element.querySelector('#modify_btn');
this.create_btn = this.element.querySelector('#create_btn') this.create_btn = this.element.querySelector('#create_btn')
this.edit_btn = this.element.querySelector('#edit_btn'); this.edit_btn = this.element.querySelector('#edit_btn');
this.title = this.element.querySelector('#title'); this.title = this.element.querySelector('#title');
...@@ -34,7 +34,7 @@ class HouseView extends EventTarget{ ...@@ -34,7 +34,7 @@ class HouseView extends EventTarget{
}); });
this.create_btn.addEventListener("click", () => { this.create_btn.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("create_house", {detail: { this.dispatchEvent(new CustomEvent("create_house", {detail: {
house_name: this.edit_fields.name.value, house_name: this.edit_fields.name.value,
house_level: this.edit_fields.house_level.value, house_level: this.edit_fields.house_level.value,
camp_location: this.edit_fields.camp_location.value, camp_location: this.edit_fields.camp_location.value,
}})) }}))
...@@ -42,7 +42,7 @@ class HouseView extends EventTarget{ ...@@ -42,7 +42,7 @@ class HouseView extends EventTarget{
this.modify_btn.addEventListener("click", () => { this.modify_btn.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("modify_house", {detail: { this.dispatchEvent(new CustomEvent("modify_house", {detail: {
house_id: this.house.id, house_id: this.house.id,
house_name: this.edit_fields.name.value ? this.edit_fields.name.value : this.house.name, house_name: this.edit_fields.name.value ? this.edit_fields.name.value : this.house.name,
house_level: this.edit_fields.house_level.value ? this.edit_fields.house_level.value : this.house.house_level, house_level: this.edit_fields.house_level.value ? this.edit_fields.house_level.value : this.house.house_level,
camp_location: this.edit_fields.camp_location.value ? this.edit_fields.camp_location.name.value : this.house.camp_location, camp_location: this.edit_fields.camp_location.value ? this.edit_fields.camp_location.name.value : this.house.camp_location,
}})) }}))
......
...@@ -25,7 +25,7 @@ class Sync{ ...@@ -25,7 +25,7 @@ class Sync{
} }
async modifyHouse(house){ async modifyHouse(house){
const response = await fetch(`/api/house/${house.id}`, { const response = await fetch(`/api/house`, {
method: "PUT", method: "PUT",
body: JSON.stringify(house), body: JSON.stringify(house),
headers: { headers: {
......
...@@ -57,7 +57,7 @@ class MyUnitsController{ ...@@ -57,7 +57,7 @@ class MyUnitsController{
async getMyUnits(){ async getMyUnits(){
this.data = []; this.data = [];
try{ try{
this.data = (await this.sync.getMyUnits()).units; this.data = await this.sync.getMyUnits();
}catch(error){ }catch(error){
console.log(error); console.log(error);
// alert('Failed to get units') // alert('Failed to get units')
...@@ -68,7 +68,7 @@ class MyUnitsController{ ...@@ -68,7 +68,7 @@ class MyUnitsController{
async getUnitsToAdd(){ async getUnitsToAdd(){
this.data = []; this.data = [];
try{ try{
this.data = (await this.sync.getUnitsToAdd()).units; this.data = await this.sync.getUnitsToAdd();
}catch(error){ }catch(error){
console.log(error); console.log(error);
// alert('Failed to get units') // alert('Failed to get units')
......
...@@ -8,7 +8,7 @@ class UnitTableController{ ...@@ -8,7 +8,7 @@ class UnitTableController{
async getAllUnits(){ async getAllUnits(){
try{ try{
const units_response = await fetch('/api/unit/all'); const units_response = await fetch('/api/unit/all');
this.view.drawTable((await units_response.json()).units); this.view.drawTable(await units_response.json());
}catch(error){ }catch(error){
console.log(error); console.log(error);
alert('Failed to get units') alert('Failed to get units')
......
...@@ -11,9 +11,9 @@ class TableView extends EventTarget{ ...@@ -11,9 +11,9 @@ class TableView extends EventTarget{
throw Error('Columns are needed'); throw Error('Columns are needed');
} }
this.$element = $(element); this.$element = $(element);
this.columns = columns; this.columns = columns;
this.$table = this.$element.find('#data_table'); this.$table = this.$element.find('#data_table');
this.datatable = this.$table.DataTable({ this.datatable = this.$table.DataTable({
columns: this.columns columns: this.columns
}); });
if(overflow){ if(overflow){
...@@ -36,7 +36,7 @@ class TableView extends EventTarget{ ...@@ -36,7 +36,7 @@ class TableView extends EventTarget{
const data_set = data.map((ele) => { const data_set = data.map((ele) => {
var d = []; var d = [];
this.columns.forEach((col) =>{ this.columns.forEach((col) =>{
const t = ele[col.term] !== undefined ? ele[col.term] : '-' const t = ele[col.term] !== undefined ? ele[col.term] : '-';
d.push(t); d.push(t);
}) })
return d; return d;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment