Commit 5a711f4b authored by Geovanny's avatar Geovanny

Added session to keep user logged in. Added functionality to assign a unit to a user

parent 2141fad0
server/database/config.json
server/node_modules/
server/.env
discord/.env
discord/__pycache__
*.pyc
__pycache__
.vscode
\ No newline at end of file
import asyncio
import discord
import discord
from requests import Session
from discord.ext import commands
from unit.manager import UnitManager
from user.manager import UserManager
from util.command_error_handler import CommandErrorHandler
from util.api_requests import Api
from settings import DISCORD_TOKEN
class ConqBot(commands.Bot):
def __init__(self, command_prefix='>'):
super().__init__(command_prefix)
self.id_to_session = {}
async def getUserSession(self, user:discord.User):
if user.id in self.id_to_session:
return self.id_to_session[user.id]
new_session = Session()
await Api.postSession('/user/d-login', {"discordId": user.id}, new_session);
self.id_to_session[user.id] = new_session
return new_session
loop = asyncio.get_event_loop()
bot = commands.Bot(command_prefix='>')
bot = ConqBot(command_prefix='>')
bot.add_cog(CommandErrorHandler(bot))
bot.add_cog(UserManager(bot))
bot.add_cog(UnitManager(bot))
@bot.event
......
......@@ -7,6 +7,7 @@ from unit.model import Unit
from util.api_requests import Api, ApiError
from .unit_parameters import *
from discord_argparse import ArgumentConverter
from util.embed_style import EmbedStyle
class UnitManager(commands.Cog):
......@@ -111,8 +112,6 @@ class UnitManager(commands.Cog):
except ApiError as error:
return await self.handleApiError(ctx, error)
if data==None:
return await ctx.send('No unit found for: ' + unit)
unit_data = Unit(**data)
embed = discord.Embed();
......@@ -159,63 +158,7 @@ class UnitManager(commands.Cog):
await self.createUnitTable(ctx, units_data)
async def createUnitTable(self, ctx, data):
max_rows = 5
max_pages = len(data) // max_rows
rem = len(data) % max_rows
cur_page = 0;
first_run = True
if rem!=0:
max_pages+=1
while True:
if first_run:
embed = self.createUnitPage(data, max_rows*cur_page, max_rows*cur_page + max_rows)
first_run = False
msg = await ctx.send(embed=embed)
reactmoji = []
if max_pages == 1 and cur_page == 0:
pass
elif cur_page == 0:
reactmoji.append('⏩')
elif cur_page == max_pages-1:
reactmoji.append('⏪')
elif cur_page > 0 and cur_page < max_pages-1:
reactmoji.extend(['⏪', '⏩'])
for react in reactmoji:
await msg.add_reaction(react)
def check_react(reaction, user):
if reaction.message.id != msg.id:
return False
if user != ctx.message.author:
return False
if str(reaction.emoji) not in reactmoji:
return False
return True
try:
res, user = await self.bot.wait_for('reaction_add', timeout=30.0, check=check_react)
except asyncio.TimeoutError:
return await msg.clear_reactions()
if '⏪' in str(res.emoji):
cur_page-= 1
embed = self.createUnitPage(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions()
await msg.edit(embed=embed)
if '⏩' in str(res.emoji):
cur_page+= 1
embed = self.createUnitPage(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions()
await msg.edit(embed=embed)
return await EmbedStyle.createPages(self.bot, ctx, data, 5, self.createUnitPage)
def createUnitPage(self, data, minI, maxI):
embed = discord.Embed(color=0x19212d)
......
......@@ -2,7 +2,9 @@ class Unit(object):
def __init__(self, id, name, type, stars=0, hp=0, pap=0, pd=0, sap=0, sd=0, bap=0, bd=0, pdf=0, sdf=0, bdf=0, leadership=0, troop_count=0, hero_level=0, speed=0, range=0, ammo=0, labour=0,
img=None,
vet_img=None):
vet_img=None,
unit_level=0,
elite_flg=None):
self.id = id
self.name = name
self.type = type
......@@ -31,6 +33,9 @@ class Unit(object):
if vet_img == None:
self.vet_img = 'https://www.conquerorsblade.com/static/img/Conqueror.cd5398b.png'
self.unit_level = unit_level
self.elite_flg = elite_flg
@classmethod
def from_dict(cls, **data):
return cls(**data)
......
import asyncio
import discord
import json
from discord.ext import commands
from discord.user import User
from unit.model import Unit
from util.api_requests import Api, ApiError
from util.embed_style import EmbedStyle
from .uu_parameters import *
class UserManager(commands.Cog):
def __init__(self, bot, loop=None):
self.bot = bot
self.loop = loop or asyncio.get_event_loop()
async def handleApiError(self, ctx, error):
return await ctx.send(error.message)
@commands.command()
async def registerUser(self, ctx):
req_body = {'discordId': ctx.message.author.id}
try:
await Api.post('/user/discord-register', req_body)
await ctx.send('Register succesful')
except ApiError as error:
return await self.handleApiError(ctx, error)
@commands.command()
async def removeAssign(self, ctx, term:str):
data = None
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/user/unit/{0}'.format(term), session)
except ApiError as error:
return await self.handleApiError(ctx, error)
await ctx.send('Do you want to remove \'{0}\'? Yes to confirm'.format(data['name']))
def check(m):
return m.channel == ctx.channel and m.author == ctx.message.author
msg = ''
try:
msg = await self.bot.wait_for('message', timeout=30.0, check=check)
except asyncio.TimeoutError:
return await ctx.send('Operation aborted')
try:
session = await self.bot.getUserSession(ctx.message.author)
await Api.deleteSession('/user/unit/{0}'.format(data['id']), session)
return await ctx.send('Unit Assignment Removed')
except ApiError as error:
return await self.handleApiError(ctx, error);
@commands.command()
async def modUnit(self, ctx, term:str, *, params:param_converter=param_converter.defaults()):
data = None
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/user/unit/{0}'.format(term), session)
except ApiError as error:
return await self.handleApiError(ctx, error)
await ctx.send('Do you want to modify \'{0}\'? Yes to confirm'.format(data['name']))
def check(m):
return m.channel == ctx.channel and m.author == ctx.message.author
msg = ''
try:
msg = await self.bot.wait_for('message', timeout=30.0, check=check)
except asyncio.TimeoutError:
return await ctx.send('Operation aborted')
try:
session = await self.bot.getUserSession(ctx.message.author)
body = params
await Api.putSession('/user/unit/{0}'.format(data['id']), body, session)
return await ctx.send('Unit Modified Successfully')
except ApiError as error:
return await self.handleApiError(ctx, error);
@commands.command()
async def assignUnit(self, ctx, term:str, *, params:param_converter=param_converter.defaults()):
data = None
try:
data = await Api.get('/unit/{0}'.format(term))
except ApiError as error:
return await self.handleApiError(ctx, error)
await ctx.send('Do you want to assign \'{0}\'? Yes to confirm'.format(data['name']))
def check(m):
return m.channel == ctx.channel and m.author == ctx.message.author
msg = ''
try:
msg = await self.bot.wait_for('message', timeout=30.0, check=check)
except asyncio.TimeoutError:
return await ctx.send('Operation aborted')
try:
session = await self.bot.getUserSession(ctx.message.author)
body = params
body['unit_id'] = data['id']
print(body)
await Api.postSession('/user/unit', body, session)
return await ctx.send('Unit Assigned Successfully')
except ApiError as error:
return await self.handleApiError(ctx, error);
@commands.command()
async def myUnits(self, ctx):
try:
session = await self.bot.getUserSession(ctx.message.author)
data = await Api.getSession('/user/units', session)
units_data = []
for item in data['units']:
units_data.append(Unit(**item))
return await EmbedStyle.createPages(self.bot, ctx, units_data, 5, self.createUnitPage)
except ApiError as error:
return await self.handleApiError(ctx, error)
def createUnitPage(self, data, minI, maxI):
embed = discord.Embed(color=0x19212d)
embed.set_author(name='TestBot')
units_str = '';
for i in range(minI, maxI):
if i < len(data):
unit = data[i]
units_str+= '[{0}] {1}\t| {2}\t| {3}\t| {4}\n'.format(unit.id, unit.name, unit.type, unit.stars, unit.unit_level)
embed.add_field(name='id\t| name\t| type\t| stars\t| level', value=units_str)
return embed
from discord_argparse import *
param_converter = ArgumentConverter(
unit_level = OptionalArgument(
str,
doc='Level of Unit',
),
eltie_flg = OptionalArgument(
bool,
doc='Is Unit Elite',
)
)
\ No newline at end of file
......@@ -6,6 +6,7 @@ from settings import API_URL_BASE
class ApiError(Exception):
def __init__(self, error_code:int, message:str=None):
self.error_code = error_code
self.message = message
......@@ -38,27 +39,38 @@ class Api:
return Api.status_code_handling(response)
@staticmethod
async def delete(url, cookies=None):
req_url = API_URL_BASE + url
response = requests.delete(req_url, cookies=cookies)
return Api.status_code_handling(response)
@staticmethod
async def getWithUser(url, uid):
enc_id = Crypto.encrypt(str(uid))
cookies = {'discord_id': enc_id}
print('ENC: ' + enc_id)
return await Api.get(url, cookies)
async def getSession(url, session):
req_url = API_URL_BASE + url
response = session.get(req_url)
return Api.status_code_handling(response)
@staticmethod
async def postWithUser(url, data, uid):
enc_id = Crypto.encrypt(str(uid))
cookies = {'discord_id': enc_id}
print('ENC: ' + enc_id)
return await Api.post(url, data, cookies)
async def postSession(url, data, session):
req_url = API_URL_BASE + url
response = session.post(req_url, json=data)
return Api.status_code_handling(response)
@staticmethod
async def putSession(url, data, session):
req_url = API_URL_BASE + url
response = session.put(req_url, json=data)
return Api.status_code_handling(response)
@staticmethod
async def putWithUser(url, data, uid):
enc_id = Crypto.encrypt(str(uid))
cookies = {'discord_id': enc_id}
print('ENC: ' + enc_id)
return await Api.put(url, data, cookies)
async def deleteSession(url, session):
req_url = API_URL_BASE + url
response = session.delete(req_url)
return Api.status_code_handling(response)
@staticmethod
......@@ -79,7 +91,6 @@ class Api:
elif response.status_code >= 400:
error_str = '[!] [{0}] Bad Request'.format(response.status_code);
print(error_str)
print(content)
raise ApiError(response.status_code, content)
elif response.status_code >= 300:
error_str = '[!] [{0}] Unexpected redirect.'.format(response.status_code)
......
import traceback
import sys
from discord.ext import commands
import discord_argparse.errors as da_errors
......@@ -43,4 +45,8 @@ class CommandErrorHandler(commands.Cog):
if ctx.command.qualified_name == 'tag list': # Check if the command being invoked is 'tag list'
return await ctx.send('I could not find that member. Please try again.')
# All other Errors not returned come here... And we can just print the default TraceBack.
print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
......@@ -7,33 +7,40 @@ from settings import ENC_DEC_MEDTHOD
class Crypto:
"""Someday, I will implement encryption and decryption. Today is not that day"""
@staticmethod
def encrypt(str_to_enc):
try:
aes_obj = AES.new(CRYPT_KEY, AES.MODE_CFB, CRYPT_SALT)
hx_enc = aes_obj.encrypt(str_to_enc.encode('utf8'))
mret = b64encode(hx_enc).decode(ENC_DEC_MEDTHOD)
return mret
except ValueError as value_error:
if value_error.args[0] == 'IV must be 16 bytes long':
raise ValueError('Encryption Error: SALT must be 16 characters long')
elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
raise ValueError('Encryption Error: Encryption key must be either 16, 24, or 32 characters long')
else:
raise ValueError(value_error)
# try:
# aes_obj = AES.new(CRYPT_KEY, AES.MODE_CFB, CRYPT_SALT)
# hx_enc = aes_obj.encrypt(str_to_enc.encode('utf8'))
# mret = b64encode(hx_enc).decode(ENC_DEC_MEDTHOD)
# return mret
# except ValueError as value_error:
# if value_error.args[0] == 'IV must be 16 bytes long':
# raise ValueError('Encryption Error: SALT must be 16 characters long')
# elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
# raise ValueError('Encryption Error: Encryption key must be either 16, 24, or 32 characters long')
# else:
# raise ValueError(value_error)
return base64encode(str_to_enc.encode('utf8')).decode('utf-8')
@staticmethod
def decrypt(enc_str):
try:
aes_obj = AES.new(CRYPT_KEY.encode('utf8'), AES.MODE_CFB, CRYPT_SALT)
str_tmp = b64decode(enc_str.encode(ENC_DEC_MEDTHOD))
str_dec = aes_obj.decrypt(str_tmp)
mret = str_dec.decode(ENC_DEC_MEDTHOD)
return mret
except ValueError as value_error:
if value_error.args[0] == 'IV must be 16 bytes long':
raise ValueError('Decryption Error: SALT must be 16 characters long')
elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
raise ValueError('Decryption Error: Encryption key must be either 16, 24, or 32 characters long')
else:
raise ValueError(value_error)
\ No newline at end of file
# try:
# aes_obj = AES.new(CRYPT_KEY.encode('utf8'), AES.MODE_CFB, CRYPT_SALT)
# str_tmp = b64decode(enc_str.encode(ENC_DEC_MEDTHOD))
# str_dec = aes_obj.decrypt(str_tmp)
# mret = str_dec.decode(ENC_DEC_MEDTHOD)
# return mret
# except ValueError as value_error:
# if value_error.args[0] == 'IV must be 16 bytes long':
# raise ValueError('Decryption Error: SALT must be 16 characters long')
# elif value_error.args[0] == 'AES key must be either 16, 24, or 32 bytes long':
# raise ValueError('Decryption Error: Encryption key must be either 16, 24, or 32 characters long')
# else:
# raise ValueError(value_error)
return base64decode(enc_str.encode('utf-8')).decode('utf8')
import discord
from asyncio import TimeoutError
class EmbedStyle:
@staticmethod
async def createPages(bot, ctx, data, max_rows, createRowsFunc):
max_pages = len(data) // max_rows
rem = len(data) % max_rows
cur_page = 0;
first_run = True
if rem!=0:
max_pages+=1
while True:
if first_run:
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
first_run = False
msg = await ctx.send(embed=embed)
reactmoji = []
if max_pages == 1 and cur_page == 0:
pass
elif cur_page == 0:
reactmoji.append('⏩')
elif cur_page == max_pages-1:
reactmoji.append('⏪')
elif cur_page > 0 and cur_page < max_pages-1:
reactmoji.extend(['⏪', '⏩'])
for react in reactmoji:
await msg.add_reaction(react)
def check_react(reaction, user):
if reaction.message.id != msg.id:
return False
if user != ctx.message.author:
return False
if str(reaction.emoji) not in reactmoji:
return False
return True
try:
res, user = await bot.wait_for('reaction_add', timeout=30.0, check=check_react)
except TimeoutError:
return await msg.clear_reactions()
if '⏪' in str(res.emoji):
cur_page-= 1
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions()
await msg.edit(embed=embed)
if '⏩' in str(res.emoji):
cur_page+= 1
embed = createRowsFunc(data, max_rows*cur_page, max_rows*cur_page + max_rows)
await msg.clear_reactions()
await msg.edit(embed=embed)
\ No newline at end of file
'use strict';
const fs = require('fs');
const MySQL = require('promise-mysql');
let config_file = fs.readFileSync('./database/config.json');
let db_config = JSON.parse(config_file);
const ENV = require('../settings');
const db = {}
let connection = MySQL.createConnection(db_config);
let connection = MySQL.createConnection({
host: ENV.DB_HOST,
port: ENV.DB_PORT,
user: ENV.DB_USER,
password: ENV.DB_PASS,
database: ENV.DB_NAME
});
connection.then((con) =>{
console.log('Database Connected');
......
......@@ -3,15 +3,22 @@
const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-body');
const session = require('koa-session')
const auth = require('./util/auth');
const unitsRouter = require('./unit/route');
const userRouter = require('./user/route');
const unitRouter = require('./unit/route');
const SESS_CONFIG = require('./session_config');
const ENV = require('./settings')
const app = new Koa();
const router = new Router();
router.use('/unit', unitsRouter.routes(), unitsRouter.allowedMethods());
app.keys = [ENV.SESS_KEY]
app.use(bodyParser());
app.use(session(SESS_CONFIG, app));
router.use('/unit', unitRouter.routes(), unitRouter.allowedMethods());
router.use('/user', userRouter.routes(), userRouter.allowedMethods());
//app.use(auth());
app.use(router.routes()).use(router.allowedMethods());
......
......@@ -62,6 +62,11 @@
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
......@@ -72,6 +77,15 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"buffer": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
"integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
"requires": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
......@@ -136,6 +150,14 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"crc": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
"integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
"requires": {
"buffer": "^5.1.0"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
......@@ -233,6 +255,11 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
},
"inflation": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
......@@ -243,16 +270,36 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-class-hotfix": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz",
"integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ=="
},
"is-generator-function": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
"integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
},
"is-type-of": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz",
"integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==",
"requires": {
"core-util-is": "^1.0.2",
"is-class-hotfix": "~0.0.6",
"isstream": "~0.1.2"
}
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
......@@ -362,6 +409,27 @@
}
}
},
"koa-session": {
"version": "5.13.1",
"resolved": "https://registry.npmjs.org/koa-session/-/koa-session-5.13.1.tgz",
"integrity": "sha512-TfYiun6xiFosyfIJKnEw0aoG5XmLIwM+K3OVWfkz84qY0NP2gbk0F/olRn0/Hrxq0f14s8amHVXeWyKYH3Cx3Q==",
"requires": {
"crc": "^3.4.4",
"debug": "^3.1.0",
"is-type-of": "^1.0.0",
"uuid": "^3.3.2"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
}
}
},
"koa-static": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
......@@ -639,6 +707,11 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
......
......@@ -6,6 +6,7 @@
"fs": "0.0.1-security",
"koa": "^2.11.0",
"koa-body": "^4.1.1",
"koa-session": "^5.13.1",
"koa-static": "^5.0.0",
"promise-mysql": "^4.1.3"
}
......
const CONFIG = {
key: 'conqbl', /** (string) cookie key (default is koa:sess) */
/** (number || 'session') maxAge in ms (default is 1 days) */
/** 'session' will result in a cookie that expires when session/browser is closed */
/** Warning: If a session cookie is stolen, this cookie will never expire */
maxAge: 86400000,
autoCommit: true, /** (boolean) automatically commit headers (default true) */
overwrite: true, /** (boolean) can overwrite or not (default true) */
httpOnly: false, /** (boolean) httpOnly or not (default true) */
signed: true, /** (boolean) signed or not (default true) */
rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */
renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
sameSite: null, /** (string) session cookie sameSite options (default null, don't set it) */
};
module.exports = CONFIG;
\ No newline at end of file
require('dotenv').config()
SETTINGS = process.env;
module.exports = SETTINGS;
\ No newline at end of file
......@@ -2,57 +2,43 @@
const db = require('../database/database');
const units = {};
const unitModel = {};
const unit_columns = ['name', 'type', 'stars', 'hp', 'pap', 'pd', 'sap', 'sd', 'bap', 'bp', 'pdf', 'sdf', 'bdf', 'leadership', 'troop_count', 'hero_level'];
const unit_columns = ['name', 'type', 'stars', 'hp', 'pap', 'pd', 'sap', 'sd', 'bap', 'bp', 'pdf', 'sdf', 'bdf', 'leadership', 'troop_count', 'hero_level', 'speed', 'range', 'ammo', 'labour', 'img', 'vet_img'];
units.getAll = async (context, next) =>{
const sql_text = 'SELECT * FROM units ORDER BY name ASC';
try{
const data = await db.con.query(sql_text);
context.response.body = {units: data};
}catch(error){
console.log(error);
context.throw(400, 'Invalid Data');
}
}
units.getUnit = async (context, next) =>{
try{
const units_data = await getUnit(context.params.term);
if(units_data.length===0){
context.throw(400, 'No Unit Found')
}
context.response.body = units_data[0];
context.status = 200;
}
catch(error){
console.log(error)
context.throw(400, 'No Unit Found')
}
unitModel.getAll = async () =>{
const sql_text = 'SELECT * FROM units ORDER BY name ASC;';
const data = await db.con.query(sql_text);
return data
}
async function getUnit(term) {
unitModel.getUnit = async (term) =>{
const unit_id = parseInt(term, 10);
if(isNaN(unit_id)){
return await getUnitByName(term);
return await unitModel.getUnitByName(term);
}else{
return await getUnitById(unit_id);
return await unitModel.getUnitById(unit_id);
}
}
async function getUnitById(id){
const sql_text = 'SELECT * FROM units WHERE id= ?';
unitModel.getUnitById = async (id) =>{
const sql_text = 'SELECT * FROM units WHERE id= ?;';
const data = await db.con.query(sql_text, [id]);
return data;
if(!data[0]){
throw Error('Unit Not Found')
}
return data[0];
}
async function getUnitByName(name){
const sql_text = 'SELECT * FROM units WHERE name LIKE ?';
const data = await db.con.query(sql_text, [`%${context.params.name}%`]);
return data;
unitModel.getUnitByName = async(name) =>{
const sql_text = 'SELECT * FROM units WHERE name LIKE ?;';
const data = await db.con.query(sql_text, [`%${name}%`]);
if(!data[0]){
throw Error('Unit Not Found')
}
return data[0];
}
units.insertUnit = async (context, next) =>{
const body = context.request.body;
unitModel.insertUnit = async (body) =>{
let column_text = 'name';
let value_text = `${db.con.escape(body.name)}`;
for (let i = 1; i < unit_columns.length; i++) {
......@@ -62,32 +48,13 @@ units.insertUnit = async (context, next) =>{
value_text += ', ' + db.con.escape(body[element]);
}
}
const sql_query = 'INSERT INTO units (' + column_text + ') VALUES (' + value_text + ');';
try{
const data = await db.con.query(sql_query);
context.response.status = 204
}catch(error){
console.log(error);
context.throw(400, 'INVALID_DATA');
}
const sql_query = `INSERT INTO units (${column_text}) VALUES (${value_text});`;
const data = await db.con.query(sql_query);
return data;
}
units.modifyUnit = async (context, next) => {
const body = context.request.body;
if(!body){
context.throw(400, 'No parameters')
}
try{
const data = getUnitById(context.params.id)
if(data.length===0){
context.throw(400, 'No Unit exists')
}
}catch(error){
console.log(error);
context.throw(400, 'Invalid unit id')
}
unitModel.modifyUnit = async (id, body) => {
let set_text = '';
for (let i = 0; i < unit_columns.length; i++) {
......@@ -100,16 +67,13 @@ units.modifyUnit = async (context, next) => {
}
}
}
const sql_query = `UPDATE units SET ${set_text} WHERE id = ?`;
try{
const data = await db.con.query(sql_query, [context.params.id]);
context.response.status = 204
}catch(error){
console.log(error);
context.throw(400, 'Invalid Data');
if(set_text===''){
throw Execption('No Update Arguments');
}
const sql_query = `UPDATE units SET ${set_text} WHERE id = ?;`;
const data = await db.con.query(sql_query, [id]);
return data;
}
module.exports = units;
\ No newline at end of file
module.exports = unitModel;
\ No newline at end of file
......@@ -4,14 +4,68 @@ const Koa = require('koa');
const Router = require('@koa/router');
const router = new Router();
const unitsModel = require('./model');
router.get('/all', unitsModel.getAll);
const unitModel = require('./model');
router.get('/all', async (context, next) =>{
const sql_text = 'SELECT * FROM units ORDER BY name ASC;';
try{
const data = await unitModel.getAll();
context.response.body = {units: data};
}catch(error){
console.log(error);
context.throw(500, 'Server Error');
}
});
router.get('/:term', unitsModel.getUnit);
router.get('/:term', async (context, next) => {
try{
const unit_data = await unitModel.getUnit(context.params.term);
if(!unit_data){
context.throw(422, 'No Unit Found')
}
context.response.body = unit_data;
context.status = 200;
}
catch(error){
console.log(error)
context.throw(422, 'No Unit Found')
}
});
router.post('/', unitsModel.insertUnit);
router.post('/', async (context, next) =>{
try{
const data = unitModel.insertUnit(context.request.body);
context.response.status = 204
}catch(error){
console.log(error);
context.throw(422, 'Invalid Data');
}
});
router.put('/:id', unitsModel.modifyUnit);
router.put('/:id', async (context, next) => {
const body = context.request.body;
const unit_id = context.params.id;
if(!body){
context.throw(422, 'No Parameters')
}
try{
const data = unitModel.getUnitById(unit_id)
if(data.length===0){
context.throw(422, 'Invalid Unit Id')
}
}catch(error){
console.log(error);
context.throw(422, 'Invalid Unit Id')
}
try{
await unitModel.modifyUnit(unit_id, body);
context.status = 204
}catch(error){
console.log(error);
context.throw(422, 'Update Failed')
}
});
module.exports = router;
\ No newline at end of file
'use strict'
const db = require('../database/database');
const unitModel = require('../unit/model');
const crypto = require('../util/crypto');
const users = {};
const userModel = {};
user.getUserFromId = async (idText, id) => {
let sql_text = `SELECT TOP 1 id, discord_id, house_id, leadership FROM users WHERE ${idText} = ?`;
try{
let data = db.con.query(sql_text,[id]);
return data;
}catch(error){
return undefined;
}
const uu_columns = ['unit_level', 'elite_flg'];
userModel.getUserFromId = async (id) => {
const sql_text = 'SELECT TOP 1 id, discord_id, house_id, leadership FROM users WHERE id = ?;';
const data = await db.con.query(sql_text,[id]);
return data[0];
}
userModel.getUserFromDiscord = async (discordId) =>{
const sql_text = 'SELECT id, discord_id, house_id, leadership FROM users WHERE discord_id = ?;';
const data = await db.con.query(sql_text, [discordId]);
return data[0];
}
users.getUser = async (context, next) => {
userModel.getUser = async (context, next) => {
let user = getUserFromId(context.params.id);
if(user){
context.response.body = {user: user};
}else{
context.throw(400, 'INVALID_ID')
context.throw(400, 'INVALID_ID');
}
};
module.exports = users;
\ No newline at end of file
userModel.getUserUnits = async(id) => {
const sql_txt = `SELECT u.*, uu.unit_level, uu.elite_flg
FROM users as us
LEFT JOIN users_units as uu ON us.id = uu.user_id
LEFT JOIN units as u ON uu.unit_id = u.id
WHERE us.id = ? ORDER BY u.name ASC;`
const data = await db.con.query(sql_txt, [id]);
return data;
}
userModel.getUserUnit = async(id, term) =>{
const unit_id = parseInt(term, 10);
if(isNaN(unit_id)){
return await userModel.getUserUnitByName(id, term);
}else{
return await userModel.getUserUnitById(id, unit_id);
}
}
userModel.getUserUnitById = async (id, unit_id) =>{
const sql_text = `SELECT u.*, uu.unit_level, uu.elite_flg
FROM users as us
LEFT JOIN users_units as uu ON us.id = uu.user_id
LEFT JOIN units as u ON uu.unit_id = u.id
WHERE us.id = ? AND uu.unit_id = ? ORDER BY u.name ASC;`;
const data = await db.con.query(sql_text, [id, unit_id]);
if(!data[0]){
throw Error('Unit Not Found')
}
return data[0];
}
userModel.getUserUnitByName = async(id, name) =>{
const sql_text = `SELECT u.*, uu.unit_level, uu.elite_flg
FROM users as us
LEFT JOIN users_units as uu ON us.id = uu.user_id
LEFT JOIN units as u ON uu.unit_id = u.id
WHERE us.id = ? AND u.name LIKE ? ORDER BY u.name ASC;`
const data = await db.con.query(sql_text, [id, `%${name}%`]);
if(!data[0]){
throw Error('Unit Not Found')
}
return data[0];
}
userModel.assignUserUnit = async(id, unit_id, body) =>{
const unit = await unitModel.getUnitById(unit_id);
let column_text = 'user_id, unit_id';
let value_text = `${db.con.escape(id)}, ${db.con.escape(unit_id)}`
if(body){
for (let i = 0; i < uu_columns.length; i++) {
const element = uu_columns[i];
if(body[element]!==undefined){
column_text += ', ' + element;
value_text += ', ' + db.con.escape(body[element]);
}
}
}
const sql_text = `INSERT INTO users_units (${column_text}) VALUES (${value_text});`
const data = await db.con.query(sql_text);
}
userModel.modifyUserUnit = async(id, unit_id, body) =>{
const unit = await unitModel.getUnitById(unit_id);
let set_text = '';
for (let i = 0; i < uu_columns.length; i++) {
const element = uu_columns[i];
if(body[element]!==undefined){
if(set_text===''){
set_text += `${element} = ${db.con.escape(body[element])}`;
}else{
set_text += `, ${element} = ${db.con.escape(body[element])}`;
}
}
}
if(set_text===''){
throw Error('No Params to Update')
}
const sql_text = `UPDATE users_units SET ${set_text} WHERE user_id = ? AND unit_id = ?`
const data = await db.con.query(sql_text, [id, unit_id]);
}
userModel.deleteUserUnit = async (id, unit_id) => {
const unit = await unitModel.getUnitById(unit_id);
const sql_text = `DELETE FROM users_units WHERE user_id = ? AND unit_id = ?;`
const data = await db.con.query(sql_text, [id, unit_id]);
}
userModel.addDiscordIdToUser = async (user_id, discord_id) =>{
const sql_text = 'UPDATE users SET discord_id = ? WHERE id = ?;';
const data = await db.con.query(sql_text, [discordId, user_id])
}
userModel.createUserWithDiscord = async (discord_id) =>{
const sql_text = 'INSERT INTO users (discord_id) VALUES (?);';
await db.con.query(sql_text, [discord_id]);
}
module.exports = userModel;
\ No newline at end of file
......@@ -4,8 +4,137 @@ const Koa = require('koa');
const Router = require('@koa/router');
const router = new Router();
const usersModel = require('./model');
const userModel = require('./model');
router.get('/user/:id', usersModel.getUser);
function checkUser(context){
if(!context.session.user_id){
context.throw(401, 'No User Logged')
}
}
router.post('/d-login', async (context, next) =>{
if(context.session.user_id && userModel.getUserFromId(context.session.user_id)){
context.throw(400, 'User is Already Logged In')
}
const body = context.request.body;
if(!body || !body.discordId){
context.throw(422, 'No Discord Id');
}
try{
const user = await userModel.getUserFromDiscord(body.discordId);
if(!user){
throw Error('No user found')
}
context.session.user_id = user.id;
context.status = 204;
}catch(error){
console.log(error);
context.throw(422, 'Login Failed')
}
});
router.get('/units', async (context, next) => {
checkUser(context);
try{
const data = await userModel.getUserUnits(context.session.user_id);
context.response.body = {units: data};
context.status = 200;
}catch(error){
console.log(error)
context.throw(400, 'No Units Found');
}
});
router.get('/unit/:term', async (context, next) =>{
checkUser(context);
try{
const data = await userModel.getUserUnit(context.session.user_id, context.params.term)
context.response.body = data;
context.status = 200;
}catch(error){
console.log(error)
context.throw(422, 'No Unit Found')
}
})
router.post('/unit', async (context, next) => {
checkUser(context);
try{
const body = context.request.body;
if(!body.unit_id){
throw Error('No Unit Id To assign')
}
await userModel.assignUserUnit(context.session.user_id, body.unit_id, body.unit_level);
context.status = 204;
}catch(error){
console.log(error);
if(error.errno===1062){
context.throw(422, 'Unit is already assigned')
}
context.throw(400, 'Could Not Assign Unit')
}
})
router.put('/unit/:unit_id', async (context, next) =>{
checkUser(context);
try{
const body = context.request.body;
if(!body){
throw Error('No Data to Modify')
}
await userModel.modifyUserUnit(context.session.user_id, context.params.unit_id, body);
context.status = 204;
}catch(error){
console.log(error);
context.throw(400, 'Could Not Modify Unit')
}
})
router.delete('/unit/:unit_id', async (context, next) =>{
checkUser(context);
try{
await userModel.deleteUserUnit(context.session.user_id, context.params.unit_id);
context.status = 204;
}catch(error){
console.log(error);
context.throw(400, 'Could Not Unassign Unit')
}
})
router.post('/discord-register', async(context, next) =>{
const body = context.request.body;
if(!body || !body.discordId){
context.throw(422, 'No Discord Id')
}
const discord_id = body.discordId;
if(context.user && !context.user.discord_id){
try{
await userModel.addDiscordIdToUser(context.user.id, discord_id);
context.status = 204;
}catch(error){
console.log(error);
context.throw(422, 'Invalid Discord Id')
}
}
let user = undefined;
try{
data = await userModel.getUserFromDiscord(discord_id);
}catch(error){
console.log(error);
context.throw(422, 'Invalid Discord Id')
}
if(!user){
try{
await userModel.createUserWithDiscord(discord_id);
context.status = 204;
}catch(error){
context.throw(422, 'Failed to create user with Discord Id')
}
}else{
context.throw(422, 'User already exists')
}
});
module.exports = router;
\ No newline at end of file
'use strict';
const db = require('../database/database');
const crypto = require('./crypto');
async function discordAuth(context, id){
let sql_text = `SELECT TOP 1 * FROM users WHERE discordId='${id}'`;
......@@ -22,9 +23,11 @@ module.exports = function(opts){
const discordId = context.cookies.get('discordId');
const sessionId = context.cookies.get('sessionId');
if(discordId!==undefined){
dec_id = crypto.decode(discordId);
discordAuth(context, discordId);
}else if(sessionId!==undefined){
sessionAuth(context, context.cookies.get('sessionId'));
dec_id = crypto.decode(dec_id);
sessionAuth(context, dec_id);
}else{
context.throw(400, 'NO ID FOUND');
}
......
'use strict'
const crypto = {};
// """Someday, I will implement encryption and decryption. Today is not that day"""
crypto.encode = (data) =>{
const buff = new Buffer(data);
return buff.toString('base64');
}
crypto.decode = (enc_data) =>{
const buff = new Buffer(enc_data, 'base64');
return buff.toString('utf-8');
}
module.exports = crypto;
\ No newline at end of file
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