class CollectiblesRepository:

    # initialize CollectiblesRepository
    def __init__(self):
        self.db = Database()
        self._commonRepository = CommonRepository()

    def get_collectibles_for_user(self, DiscordUserID):
        try:
            result = eval(str(self.db.select(['*'], 'discordusercollectibles'
                + ' JOIN collectibles ON collectibles.CollectibleID = discordusercollectibles.CollectibleID',
                'discordusercollectibles.DiscordUserID = %s', [DiscordUserID])))
            return result, StatusCodes.OK
        except:
            return 'error in get_collectibles_for_user', StatusCodes.INTERNAL_SERVER_ERROR
    
    def purchase(self, rDiscordUserID, rCollectibleName):
        try:
            userCurrenyQuery = self.db.select(['Currency'], 'discordusers', 'DiscordUserID = %s', [rDiscordUserID]).getRows()
            if len(userCurrenyQuery) > 0:
                userCurrency = userCurrenyQuery[0]['Currency']
                collectibleQuery = self.db.select(['*'], 'collectibles', 'Name = %s', [rCollectibleName]).getRows()
                if len(collectibleQuery) > 0:
                    collectibleItem = collectibleQuery[0]
                    if len(self.db.select(['*'], 'discordusercollectibles', 'DiscordUserID = %s AND CollectibleID = %s', [rDiscordUserID, collectibleItem['CollectibleID']]).getRows()) == 0:
                        # make sure the user has enough currency to purchase this collectible
                        collectiblePrice = int(collectibleItem['Currency'])
                        if userCurrency >= collectiblePrice:
                            # insert into DiscorduserCollectibles table
                            self.db.insertOne('discordusercollectibles', ['DiscordUserID', 'CollectibleID', 'Date'], {
                                'DiscordUserID': rDiscordUserID,
                                'CollectibleID': collectibleItem['CollectibleID'],
                                'Date': str(datetime.datetime.now())
                            })
                            # decrement the user's currency
                            print('line 40')
                            self._commonRepository.subtract_from_user_currency(rDiscordUserID, collectiblePrice)
                            print('line 42')
                            # return OK
                            return f'Successfully purchased {rCollectibleName}', StatusCodes.OK
                        else:
                            # the user does not have enough currency to purchase this collectible
                            return 'Insufficient funds', StatusCodes.IM_A_TEAPOT
                    else:
                        # the user has already purchased this collectible
                        return 'the user has already purchased this collectible', StatusCodes.CONFLICT
                else:
                    # no collectibles in the DB with a matching name
                    return f"Could not find a collectible with name '{rCollectibleName}'", StatusCodes.NOT_FOUND
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR
示例#2
0
class GetUserInfoRepository:

    # initialize GetUserInfoRepository
    def __init__(self):
        self.db = Database()

    # retrieve user from DB
    def get_user(self, userid):
        dt = self.db.select([
            'DiscordUserID', 'UserName', 'UserHash', 'Currency', 'LastDaily',
            'Link AS ProfilePictureURL'
        ], 'discordusers LEFT OUTER JOIN resources ON resources.ResourceID = discordusers.ResourceID',
                            'discorduserid = ' + str(userid))
        return eval(str(dt.getRows()[0]))
示例#3
0
class DTORepository:

    # initialize DTORepository
    def __init__(self):
        self.db = Database()
    
    def __getKeys(self, entity):
        props = []
        for key in entity.keys():
            props.append(key)
        return props

    # returns the table passed
    def selectAll(self, table):
        dt = self.db.select(['*'], table)
        print('asdf')
        print(str(dt))
        print('asdf')
        return eval(str(dt))
    
    # retrieve information for the get id method on the controller
    def insert(self, table, entity):
        props = self.__getKeys(entity)
        return self.db.insertOne(table, props, entity)
    
    def select(self, table, IDColumn, ID):
        dt = self.db.select(['*'], table, f"{IDColumn} = %s", [ID])
        print(str(dt))
        return eval(str(dt))
    
    def update(self, table, entity, where = '', values = []):
        props = self.__getKeys(entity)
        return self.db.update(table, props, entity, where, values)
    
    def delete(self, table, where = '', values = []):
        dt = self.db.delete(table, where, values)
        return eval(str(dt))
示例#4
0
class CommonRepository:

    # initialize RaffleRepository
    def __init__(self):
        self.db = Database()
    
    def add_currency_to_table(self, table, idcolumn, id, amount):
        currency = self.db.select(['Currency'], table, f"{idcolumn} = %s", [id]).getRows()[0]['Currency']
        newTotal = int(currency) + int(amount)
        self.db.update(table, ['Currency'], {
            'Currency': newTotal
        }, f"{idcolumn} = %s", [id])
    
    # adds amount to specified users's currency
    def add_currency_to_raffle(self, raffleid, amount):
        self.add_currency_to_table('raffles', 'RaffleID', raffleid, amount)
    
    # adds amount to specified users's currency
    def add_to_user_currency(self, discorduserid, amount):
        self.add_currency_to_table('discordusers', 'DiscordUserID', discorduserid, amount)
    
    # subtracts amount from specified users's currency
    def subtract_from_user_currency(self, discorduserid, amount):
        self.add_to_user_currency(discorduserid, -1 * amount)
示例#5
0
class ProfileRepository:

    # initialize ProfileRepository
    def __init__(self):
        self.db = Database()

    def trim(self, string):
        return string[:string.index('?')] if '?' in string else string

    def dtToMapStr(self, dt):
        result = ''
        counter = 0
        for row in dt:
            result += f"{row['k']}!!!!!{self.trim(row['v'])}"
            counter += 1
            result += '!!!!!!!!!!' if counter < len(dt) else ''
        return 'None' if result == '' else result

    def get_url(self, discorduserid):
        try:
            # SELECT discordusers.DiscordUserID, discordusers.UserName, discordusers.UserHash,
            # discordusers.Currency, discordusers.LastDaily, resources.Link AS ProfilePictureURL
            # FROM discordusers
            # JOIN resources ON discordusers.ResourceID = resources.ResourceID
            # WHERE discorduserid = '309176098590294026';
            dt = self.db.select([
                'discordusers.DiscordUserID', 'discordusers.UserName',
                'discordusers.UserHash', 'discordusers.Currency',
                'discordusers.LastDaily', 'resources.Link AS ProfilePictureURL'
            ], 'discordusers JOIN resources ON discordusers.ResourceID = resources.ResourceID',
                                'DiscordUserID = %s', [discorduserid])
            if len(dt.getRows()) > 0:
                discorduser = eval(str(dt.getRows()[0]))
                # SELECT DISTINCT collectibles.Name, resources.Link
                # FROM discordusercollectibles
                # JOIN collectibles ON discordusercollectibles.CollectibleID = collectibles.CollectibleID
                # JOIN resources ON collectibles.ResourceID = resources.ResourceID
                # WHERE discorduserid = '309176098590294026';
                collectibles = []
                dt = self.db.select(
                    ['DISTINCT collectibles.Name AS k', 'resources.Link AS v'],
                    '''discordusercollectibles
                    JOIN collectibles ON discordusercollectibles.CollectibleID = collectibles.CollectibleID
                    JOIN resources ON collectibles.ResourceID = resources.ResourceID''',
                    'discorduserid = %s', [discorduserid])
                if len(dt.getRows()) > 0:
                    collectibles = eval(str(dt))
                # collectibles = []

                # SELECT DISTINCT socialmedias.Title, resources.Link
                # FROM discordusersocialmedias
                # JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                # JOIN resources ON socialmedias.ResourceID = resources.ResourceID
                # WHERE discorduserid = '309176098590294026';
                socialmedias = []
                dt = self.db.select([
                    'DISTINCT socialmedias.Title AS k', 'resources.Link AS v'
                ], '''discordusersocialmedias
                    JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                    JOIN resources ON socialmedias.ResourceID = resources.ResourceID''',
                                    'discorduserid = %s', [discorduserid])
                if len(dt.getRows()) > 0:
                    socialmedias = eval(str(dt))

                collectiblesmap = self.dtToMapStr(collectibles)
                socialmediasmap = self.dtToMapStr(socialmedias)
                url = ""
                url += f"app/profile?Currency={discorduser['Currency']}&DiscordUserID={discorduser['DiscordUserID']}&"
                url += f"LastDaily={discorduser['LastDaily']}&ProfilePictureURL={self.trim(discorduser['ProfilePictureURL'])}&"
                url += f"UserName={discorduser['UserName']}&UserHash={discorduser['UserHash']}&"
                url += f"Collectibles={collectiblesmap}&SocialMedias={socialmediasmap}"
                return url, StatusCodes.OK
            else:
                return 'user not found', StatusCodes.NOT_FOUND
        except Exception as e:
            return eval(str(e)), StatusCodes.INTERNAL_SERVER_ERROR
class CurrencyRepository:

    # initialize CurrencyRepository
    def __init__(self):
        self.db = Database()

    def insertTransaction(self, fromID, toID, time, amount):
        self.db.insertOne(
            'currencytransactions',
            ['FromDiscordUserID', 'ToDiscordUserID', 'Date', 'Amount'], {
                'FromDiscordUserID': fromID,
                'ToDiscordUserID': toID,
                'Date': time,
                'Amount': amount
            })

    def daily(self, discordUserID, amount):
        try:
            dt = self.db.select(['*'], 'discordusers', 'DiscordUserID = %s',
                                [discordUserID])
            user = dt.getRows()[0] if len(dt.getRows()) == 1 else None
            if user != None:
                now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                timeUntilNextDaily = 0
                if user['LastDaily'] == None:
                    timeUntilNextDaily = 60 * 60 * 24
                else:
                    nowtime = datetime.datetime.now().timestamp()
                    thentime = datetime.datetime.fromisoformat(
                        str(user['LastDaily'])).timestamp()
                    timeUntilNextDaily = int(thentime + (60 * 60 * 24) -
                                             nowtime)
                if timeUntilNextDaily < 0:
                    userJSON = eval(str(user))
                    userJSON['LastDaily'] = now
                    userJSON['Currency'] = int(userJSON['Currency']) + amount
                    self.insertTransaction(0, discordUserID, now, amount)
                    self.db.update('discordusers', ['Currency', 'LastDaily'],
                                   userJSON, 'DiscordUserID = %s',
                                   [discordUserID])
                    return True
                else:
                    return timeUntilNextDaily * 1000
            else:
                return False
        except:
            return False

    def transfer(self, senderID, receiverID, amount):
        try:
            if amount > 0:
                dt1 = self.db.select(['*'], 'discordusers',
                                     'DiscordUserID = %s', [senderID])
                dt2 = self.db.select(['*'], 'discordusers',
                                     'DiscordUserID = %s', [receiverID])
                sendingUser = dt1.getRows()[0] if len(
                    dt1.getRows()) == 1 else None
                receivingUser = dt2.getRows()[0] if len(
                    dt2.getRows()) == 1 else None
                if sendingUser != None and receivingUser != None:
                    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    sendingUserJSON = eval(str(sendingUser))
                    receivingUserJSON = eval(str(receivingUser))
                    sendingUserJSON['Currency'] = int(
                        sendingUserJSON['Currency']) - amount
                    receivingUserJSON['Currency'] = int(
                        receivingUserJSON['Currency']) + amount
                    self.insertTransaction(senderID, receiverID, now, amount)
                    self.db.update('discordusers', ['Currency'],
                                   sendingUserJSON, 'DiscordUserID = %s',
                                   [senderID])
                    self.db.update('discordusers', ['Currency'],
                                   receivingUserJSON, 'DiscordUserID = %s',
                                   [receiverID])
                    return True
                else:
                    return False
            else:
                return 'You cannot transfer a negative amount.'
        except:
            return False
class AuthenticationRepository:

    # initialize AuthenticationRepository
    def __init__(self):
        self.db = Database()

    def loginClient(self, token, username, password):
        if token != '' or (username == 'username' and password == 'password'):
            userID = ''
            validToken = False
            jwt = JWTHelper(Config.secretkey, 'HS256')
            if token != '':
                decodedToken = jwt.decode(token)
                if decodedToken != 'Token Expired':
                    validToken = True
                userID = dict(decodedToken)['DiscordUserID']
            else:
                validToken = True
            if validToken:
                now = round(time.time())
                payload = {
                    'iat': now,
                    'exp': now + Config.tokenlifetime,
                    'DiscordUserID': userID,
                    'client': 'angular'
                }
                resp = {'jwt': jwt.encode(payload)}
                return resp
        return False

    def loginBot(self, token):
        jwt = JWTHelper(Config.rsapublickey, 'RS256')
        decodedToken = jwt.decode(token)
        if decodedToken != 'Token Expired':
            jwt = JWTHelper(Config.secretkey, 'HS256')
            now = round(time.time())
            payload = {
                'iat': now,
                'exp': now + Config.tokenlifetime,
                'client': 'bot'
            }
            resp = {'jwt': jwt.encode(payload)}
            return resp
        else:
            return False

    def getTokenForUser(self, username):
        userid = ''
        dt = self.db.select(['DiscordUserID'], 'discordusers', 'UserName = %s',
                            [username])
        print(dt.getRows()[0]['DiscordUserID'])
        if len(dt.getRows()) == 1:
            userid = dt.getRows()[0]['DiscordUserID']
        print(userid)
        if userid != '':
            jwt = JWTHelper(Config.secretkey, 'HS256')
            now = round(time.time())
            payload = {
                'iat': now,
                'exp': now + Config.tokenlifetime,
                'DiscordUserID': userid,
                'client': 'angular'
            }
            resp = {'jwt': jwt.encode(payload)}
            return resp
        else:
            return False
示例#8
0
class SocialMediaRepository:

    # initialize SocialMediaRepository
    def __init__(self):
        self.db = Database()
        self._commonRepository = CommonRepository()

    # Lists the different social media platforms that this bot supports
    def list_all(self):
        try:
            # SELECT Title AS Platform, URL AS Link, Link AS Icon
            #   FROM socialmedias
            #   JOIN resources ON socialmedias.ResourceID = resources.ResourceID;
            socialmedias = self.db.select(['Title AS Platform', 'URL AS Link', 'Link AS Icon'], \
                'socialmedias JOIN resources ON socialmedias.ResourceID = resources.ResourceID')
            return eval(str(socialmedias)), StatusCodes.OK
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # Adds the specified <socialmedia> platform and <handle> to the sending user's profile
    def add_social_media(self, rDiscordUserID, rPlatform, rLink):
        try:
            # SELECT * FROM socialmedias WHERE Title = 'Facebook';
            socialMedia = self.db.select(['SocialMediaID'], 'socialmedias',
                                         'Title = %s', [rPlatform]).getRows()
            if len(socialMedia) > 0:
                smID = socialMedia[0]['SocialMediaID']
                # INSERT INTO discordusersocialmedias (DiscordUserID, SocialMediaID, Handle)
                #   VALUES ('309176098590294026', '1', 'Nathan Gawith');
                if len(
                        self.db.select(
                            ['*'], 'discordusersocialmedias',
                            'DiscordUserID = %s AND SocialMediaID = %s',
                            [rDiscordUserID, smID]).getRows()) > 0:
                    self.db.update(
                        'discordusersocialmedias', ['Handle'],
                        {'Handle': rLink},
                        'DiscordUserID = %s AND SocialMediaID = %s',
                        [rDiscordUserID, smID])
                else:
                    self.db.insertOne(
                        'discordusersocialmedias',
                        ['DiscordUserID', 'SocialMediaID', 'Handle'], {
                            'DiscordUserID': rDiscordUserID,
                            'SocialMediaID': smID,
                            'Handle': rLink
                        })
                return '', StatusCodes.OK
            else:
                return f"'{rPlatform}' was not found in the socialmedias table", StatusCodes.NOT_FOUND
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # returns information about the specific social media for the specified user
    def get_social_media(self, rDiscordUserID, rSocialMediaName):
        try:
            # SELECT * FROM socialmedias WHERE Title = 'Facebook';
            socialMedia = self.db.select(['SocialMediaID'], 'socialmedias',
                                         'Title LIKE %s',
                                         [rSocialMediaName]).getRows()
            if len(socialMedia) > 0:
                # SELECT Title AS Platform, Handle AS Link, Link AS ICON
                #   FROM discordusersocialmedias
                #   INNER JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                #   INNER JOIN resources ON socialmedias.ResourceID = resources.ResourceID
                #   WHERE DiscordUserID = '123456789123456789' AND Title LIKE 'Facebook';
                qeryResult = self.db.select(['Title AS Platform', 'Handle AS Link', 'Link AS ICON'], \
                    '''discordusersocialmedias
                    INNER JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                    INNER JOIN resources ON socialmedias.ResourceID = resources.ResourceID''',
                    'DiscordUserID = %s AND Title LIKE %s', [rDiscordUserID, rSocialMediaName])
                return eval(str(qeryResult)), StatusCodes.OK
            else:
                return f"'{rSocialMediaName}' was not found in the socialmedias table", StatusCodes.NOT_FOUND
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # Adds the specified <socialmedia> platform and <handle> to the sending user's profile
    def get_social_medias(self, rDiscordUserID):
        try:
            return self.get_social_media(rDiscordUserID, '%')
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # deletes from discordusersocialmedias for the specific social media and discorduser
    def delete_social_media(self, rDiscordUserID, rSocialMediaName):
        try:
            # SELECT * FROM socialmedias WHERE Title = 'Facebook';
            socialMedia = self.db.select(['SocialMediaID'], 'socialmedias',
                                         'Title LIKE %s',
                                         [rSocialMediaName]).getRows()
            if len(socialMedia) > 0:
                # SELECT Title AS Platform, Handle AS Link, Link AS ICON
                #   FROM discordusersocialmedias
                #   INNER JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                #   INNER JOIN resources ON socialmedias.ResourceID = resources.ResourceID
                #   WHERE DiscordUserID = '123456789123456789' AND Title LIKE 'Facebook';
                if len(self.db.select(['Title AS Platform', 'Handle AS Link', 'Link AS ICON'], \
                    '''discordusersocialmedias
                    INNER JOIN socialmedias ON discordusersocialmedias.SocialMediaID = socialmedias.SocialMediaID
                    INNER JOIN resources ON socialmedias.ResourceID = resources.ResourceID''',
                    'DiscordUserID = %s AND Title LIKE %s', [rDiscordUserID, rSocialMediaName]).getRows()) > 0:
                    self.db.delete(
                        'discordusersocialmedias',
                        'DiscordUserID = %s AND SocialMediaID = %s',
                        [rDiscordUserID,
                         str(socialMedia[0]['SocialMediaID'])])
                    return 'Success', StatusCodes.OK
                else:
                    return 'This user does not have this specific social media', StatusCodes.NOT_FOUND
            else:
                return f"'{rSocialMediaName}' was not found in the socialmedias table", StatusCodes.NOT_FOUND
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR
class AddBatchRepository:

    # initialize AddBatchRepository
    def __init__(self):
        self.db = Database()

    # add batch of servers to the database
    def add_batch_servers(self, servers: list):
        try:
            dtoRepository = DTORepository()
            currentServers = dtoRepository.selectAll('servers')
            dbserverids = [s['ServerID'] for s in currentServers]
            for server in servers:
                print(server['ServerID'])
                if server['ServerID'] in dbserverids:
                    dtoRepository.update('servers', server, 'ServerID = %s',
                                         [server['ServerID']])
                else:
                    dtoRepository.insert('servers', server)
            return True
        except Exception as e:
            print(e)
            return False

    # add batch of users to the database
    def add_batch_users(self, users: list):
        try:
            # get list of serverids from the atabase
            dtoRepository = DTORepository()
            currentServers = dtoRepository.selectAll('servers')
            dbserverids = [s['ServerID'] for s in currentServers]
            currentDiscordUsers = dtoRepository.selectAll('discordusers')
            dbdiscorduserids = [
                d['DiscordUserID'] for d in currentDiscordUsers
            ]
            for user in users:
                for server in user['Servers']:
                    if not server['ServerID'] in dbserverids:
                        # add each discorduserserver relationship to the DB
                        server['DiscordUserID'] = user['DiscordUserID']
                        self.db.insertOne(
                            'discorduserservers',
                            ['DiscordUserID', 'ServerID', 'JoinDate'],
                            eval(server))
                # add user if all of the ServerIDs for that user have allready been added to the DB
                del user['Servers']
                # if the user is new, insert
                if not user['DiscordUserID'] in dbdiscorduserids:
                    # insert profile picture
                    self.db.insertOne('resources', ['Link'],
                                      {'Link': user['ProfilePicture']})
                    id = self.db.select(['MAX(ResourceID) AS id'],
                                        'resources').getRows()[0]['id']
                    del user['ProfilePicture']
                    user['ResourceID'] = id
                    # add the user to the list of users to add
                    user['DiscordUserID'] = user['DiscordUserID']
                    self.db.insertOne('discordusers', [
                        'DiscordUserID', 'UserName', 'UserHash', 'Currency',
                        'LastDaily', 'RaffleID'
                    ], user)
                    # insert into discordusersocialmedias
                    self.db.insertOne(
                        'discordusersocialmedias',
                        ['DiscordUserID', 'SocialMediaID', 'Handle'], {
                            'DiscordUserID': user['DiscordUserID'],
                            'SocialMediaID': '8',
                            'Handle': f"{user['UserName']}#{user['UserHash']}"
                        })
                # if the user already exists in the db, update
                else:
                    oldUser = self.db.select(
                        ['DiscordUserID', 'ResourceID'], 'discordusers',
                        'DiscordUserID = %s',
                        [user['DiscordUserID']]).getRows()[0]
                    oldProfilePictureLink = self.db.select(
                        ['Link'], 'resources', 'ResourceID = \'' +
                        str(oldUser['ResourceID']) + '\'').getRows()[0]['Link']
                    id = str(oldUser['ResourceID'])
                    # if the profilepicture is new, update resources table
                    if not oldProfilePictureLink == user['ProfilePicture']:
                        dtoRepository.update(
                            'resources', {'Link': user['ProfilePicture']},
                            'ResourceID = \'' + str(oldUser['ResourceID']) +
                            '\'')
                    del user['ProfilePicture']
                    user['ResourceID'] = id
                    # update discorduser
                    dtoRepository.update(
                        'discordusers', user, 'DiscordUserID =  \'' +
                        oldUser['DiscordUserID'] + '\'')
                    # insert or update discordusersocialmedias
                    if len(
                            self.db.select(
                                ['*'], 'discordusersocialmedias',
                                'DiscordUserID = %s AND SocialMediaID = 8',
                                [user['DiscordUserID']]).getRows()) > 0:
                        self.db.update(
                            'discordusersocialmedias',
                            ['DiscordUserID', 'SocialMediaID', 'Handle'], {
                                'DiscordUserID': user['DiscordUserID'],
                                'SocialMediaID': '8',
                                'Handle':
                                f"{user['UserName']}#{user['UserHash']}"
                            }, 'DiscordUserID =  %s', [user['DiscordUserID']])
                    else:
                        self.db.insertOne(
                            'discordusersocialmedias',
                            ['DiscordUserID', 'SocialMediaID', 'Handle'], {
                                'DiscordUserID': user['DiscordUserID'],
                                'SocialMediaID': '8',
                                'Handle':
                                f"{user['UserName']}#{user['UserHash']}"
                            })
            return True
        except Exception as e:
            print(e)
            return False
示例#10
0
class RaffleRepository:

    # initialize RaffleRepository
    def __init__(self):
        self.db = Database()
        self._commonRepository = CommonRepository()

    # returns JSON representing all of the users participating in this raffle
    def __get_discordusers_in_raffle(self, raffleID):
        return eval(
            str(
                self.db.select([
                    'discordusers.DiscordUserID', 'discordusers.UserName',
                    'discordusers.Currency', 'discordusers.UserHash',
                    'resources.Link AS ProfilePicture'
                ], '''discorduserraffles
            LEFT OUTER JOIN discordusers ON discordusers.DiscordUserID = discorduserraffles.DiscordUserID
            LEFT OUTER JOIN resources ON resources.ResourceID = discordusers.ResourceID''',
                               f"discorduserraffles.RaffleID = '{raffleID}'")))

    # starts a new raffle
    def start_raffle(self, rName, rDiscordUserID, rServerID, rDuration,
                     rSeedAmount):
        try:
            userCurrenyQuery = self.db.select(
                ['Currency'], 'discordusers',
                f"DiscordUserID = '{rDiscordUserID}'").getRows()
            if len(userCurrenyQuery) > 0:
                userCurrency = userCurrenyQuery[0]['Currency']
                # make sure the user has enough currency to start this raffle
                if userCurrency >= rSeedAmount:
                    endTime = None
                    # calculate end datetime of this raffle
                    if rDuration >= 0:
                        nowtime = datetime.datetime.now().timestamp()
                        endTime = str(
                            datetime.datetime.fromtimestamp(
                                int(nowtime + (rDuration / 1000))))
                    # create raffle in Raffles table
                    if self.db.insertOne(
                            'raffles', [
                                'ServerID', 'Name', 'EndTime', 'Currency',
                                'DiscordUserID'
                            ], {
                                'ServerID': rServerID,
                                'Name': rName,
                                'EndTime': endTime,
                                'Currency': rSeedAmount,
                                'DiscordUserID': rDiscordUserID
                            }):
                        # get the new RaffleID
                        maxID = self.db.select(['MAX(RaffleID) AS NewID'],
                                               'raffles').getRows()
                        newRaffleID = 1
                        if (len(maxID) > 0):
                            newRaffleID = maxID[0]['NewID']
                        # insert into DiscordUserRaffles table
                        self.db.insertOne(
                            'discorduserraffles',
                            ['DiscordUserID', 'RaffleID', 'JoinDate'], {
                                'DiscordUserID': rDiscordUserID,
                                'RaffleID': newRaffleID,
                                'JoinDate': str(datetime.datetime.now())
                            })
                        # decrement the user's currency
                        self._commonRepository.subtract_from_user_currency(
                            rDiscordUserID, rSeedAmount)
                        # return OK
                        return '', StatusCodes.OK
                    else:
                        # conflict when inserting, so a raffle with this name already exists
                        return f"A raffle with the name {rName} already exists on this server", StatusCodes.CONFLICT
            # the user does not have enough currency to start this raffle
            return 'Insufficient funds', StatusCodes.IM_A_TEAPOT
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # adds currency to a raffle
    def join_raffle(self, rDiscordUserID, rServerID, rRaffle, rAmount):
        try:
            userCurrenyQuery = self.db.select(
                ['Currency'], 'discordusers',
                f"DiscordUserID = '{rDiscordUserID}'").getRows()
            if len(userCurrenyQuery) > 0:
                userCurrency = userCurrenyQuery[0]['Currency']
                # make sure the user has enough currency to start this raffle
                if userCurrency >= rAmount:
                    # if a raffle exists on this server with the same name
                    raffleQueryDataTable = self.db.select(
                        ['RaffleID', 'Currency'], 'raffles',
                        f"Name = '{rRaffle}' AND ServerID = '{rServerID}'")
                    print(str(raffleQueryDataTable))
                    raffleQueryDataTable = raffleQueryDataTable.getRows()
                    if len(raffleQueryDataTable) == 1:
                        # get the RaffleID
                        raffleID = raffleQueryDataTable[0]['RaffleID']
                        currentCurrency = raffleQueryDataTable[0]['Currency']
                        # insert into DiscordUserRaffles table
                        self.db.insertOne(
                            'discorduserraffles',
                            ['DiscordUserID', 'RaffleID', 'JoinDate'], {
                                'DiscordUserID': rDiscordUserID,
                                'RaffleID': raffleID,
                                'JoinDate': str(datetime.datetime.now())
                            })
                        # update the Raffles table
                        self._commonRepository.add_currency_to_raffle(
                            raffleID, rAmount)
                        # decrement the user's currency
                        self._commonRepository.subtract_from_user_currency(
                            rDiscordUserID, rAmount)
                        # query the DB for the return statement
                        raffle = eval(
                            str(
                                self.db.select(
                                    ['*'], 'raffles',
                                    f"RaffleID = '{raffleID}'").getRows()[0]))
                        discordusers = self.__get_discordusers_in_raffle(
                            raffleID)
                        # return OK
                        return {
                            'DiscordUsers': discordusers,
                            'Raffle': raffle
                        }, StatusCodes.OK
                    else:
                        # raffle with the passed name was not found on the server
                        return f"A raffle with the name {rRaffle} was not found on this server",\
                            StatusCodes.NOT_FOUND
            # the user does not have enough currency to start this raffle
            return 'Insufficient funds', StatusCodes.IM_A_TEAPOT
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # returns all of the raffles that are currently available on the specified server
    def get_raffles(self, rServerID):
        try:
            raffles = self.db.select(['*'], 'raffles',
                                     f"ServerID = '{rServerID}'").getRows()
            # return list of raffleinfos
            return [{
                'DiscordUsers':
                self.__get_discordusers_in_raffle(raffle['RaffleID']),
                'Raffle':
                eval(str(raffle))
            } for raffle in raffles], StatusCodes.OK
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # returns all of the raffles that are currently available on the specified server
    def get_historic_raffles(self, rDiscordUserID):
        try:
            result = self.db.select([
                'discorduserraffles.RaffleID',
                'CASE WHEN rafflehistory.DiscordUserID IS NOT NULL THEN rafflehistory.DiscordUserID ELSE raffles.DiscordUserID END AS DiscordUserID',
                'CASE WHEN rafflehistory.ServerID IS NOT NULL THEN rafflehistory.ServerID ELSE raffles.ServerID END AS ServerID',
                'CASE WHEN rafflehistory.Name IS NOT NULL THEN rafflehistory.Name ELSE raffles.Name END AS Name',
                'CASE WHEN rafflehistory.EndTime IS NOT NULL THEN rafflehistory.EndTime ELSE raffles.EndTime END AS EndTime',
                'CASE WHEN rafflehistory.Currency IS NOT NULL THEN rafflehistory.Currency ELSE raffles.Currency END AS Currency',
                'rafflehistory.WinnerDiscordUserID'
            ], '''
                discorduserraffles
                LEFT JOIN rafflehistory ON discorduserraffles.RaffleID = rafflehistory.RaffleID
                LEFT JOIN raffles ON discorduserraffles.RaffleID = raffles.RaffleID''',
                                    'discorduserraffles.DiscordUserID = %s AND (raffles.DiscordUserID IS NOT NULL OR rafflehistory.DiscordUserID IS NOT NULL)',
                                    [rDiscordUserID])
            # return list of raffleinfos
            return eval(str(result)), StatusCodes.OK
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # returns all of the raffles that are going to end within the given number of milliseconds
    def get_raffles_ending_in_millis(self, rMillis):
        try:
            # calculate time
            nowtime = datetime.datetime.now().timestamp()
            endTime = str(
                datetime.datetime.fromtimestamp(int(nowtime +
                                                    (rMillis / 1000))))
            # query Raffles table
            raffles = self.db.select(['*'], 'raffles',
                                     f"EndTime < '{endTime}'")
            # return list of raffles
            return eval(str(raffles)), StatusCodes.OK
        except:
            # some error has occurred
            return '', StatusCodes.INTERNAL_SERVER_ERROR

    # ends the specified raffle if the user who
    #  requested this is qualified to end the raffle
    def end_raffle(self, rDiscordUserID, rServerID, rRaffle):
        try:
            print('end_raffle')
            raffle = self.db.select(['*'], 'raffles',\
                f"ServerID = '{rServerID}' AND Name = '{rRaffle}'").getRows()
            if len(raffle) == 1:
                # if the user who is ending this raffle is the bot or
                #  is the user who started this raffle
                if rDiscordUserID in ['0', raffle[0]['DiscordUserID']]:
                    discordusersinraffle = self.__get_discordusers_in_raffle(
                        raffle[0]['RaffleID'])
                    winner = random.choice(discordusersinraffle)
                    # add the total currency for this raffle to the winner's currency
                    self._commonRepository.add_to_user_currency(
                        winner['DiscordUserID'], raffle[0]['Currency'])
                    nowtime = datetime.datetime.now().timestamp()
                    endTime = datetime.datetime.fromtimestamp(int(nowtime))
                    self.db.insertOne(
                        'rafflehistory', [
                            'RaffleID', 'ServerID', 'Name', 'EndTime',
                            'Currency', 'DiscordUserID', 'WinnerDiscordUserID'
                        ], {
                            'RaffleID': raffle[0]['RaffleID'],
                            'ServerID': raffle[0]['ServerID'],
                            'Name': raffle[0]['Name'],
                            'EndTime': str(endTime),
                            'Currency': raffle[0]['Currency'],
                            'DiscordUserID': raffle[0]['DiscordUserID'],
                            'WinnerDiscordUserID': winner['DiscordUserID']
                        })
                    print('before delete')
                    # delete the raffle
                    self.db.delete('raffles', 'RaffleID = %s',
                                   [raffle[0]['RaffleID']])
                    print('after delete')
                    return {
                        'Winner': winner,
                        'RaffleInfo': {
                            'DiscordUsers': discordusersinraffle,
                            'Raffle': eval(str(raffle[0]))
                        }
                    }, StatusCodes.OK
                else:
                    # only the user who started the raffle or the bot can end a raffle
                    return 'You do not have the authority to end this raffle',\
                        StatusCodes.FORBIDDEN
            else:
                # raffle with the passed name was not found on the server
                return f"A raffle with the name {rRaffle} was not found on this server",\
                    StatusCodes.NOT_FOUND
        except Exception as e:
            # some error has occurred
            return e, StatusCodes.INTERNAL_SERVER_ERROR