Example #1
0
class editCharacterTraitAdd(APIResponse):
    def __init__(self):
        super(editCharacterTraitAdd, self).__init__(config, session, min_access_level=2, accepted_input = {
            'traitId': (MUST, validator_str_range(1, 20)), # I'm validating the trait later because I also need trait data
            'charId': (MUST, validator_character),
        })
    @web_security(sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId'))))
    def mGET(self):
        lid = getLanguage(self.session, dbm)
        issuer = self.session.discord_userid
        character = self.input_data['charId']
        trait_id = self.input_data['traitId']
        charId = character['id']

        try:
            _ = dbm.getTrait(charId, trait_id)
            raise WebException("The character already has this trait", 400)
        except ghostDB.DBException as e:
            pass
        
        trait =  dbm.validators.getValidateTrait(trait_id).get()
        
        if trait['textbased']:
            textval = ""
            dbm.db.insert("CharacterTrait", trait=trait_id, playerchar=charId, cur_value = 0, max_value = 0, text_value = textval, pimp_max = 0)
            dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.TEXT_VALUE, textval, '', "web edit")
        else:
            numval = 0
            pimp = 6 if trait['traittype'] in ['fisico', 'sociale', 'mentale'] else 0
            dbm.db.insert("CharacterTrait", trait=trait_id, playerchar=charId, cur_value = numval, max_value = numval, text_value = "", pimp_max = pimp)
            dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.MAX_VALUE, numval, '',  "web edit")

        return dbm.getTrait_LangSafe(charId, trait_id, lid)
Example #2
0
class editCharacterTraitNumberCurrent(APIResponse): # no textbased
    def __init__(self):
        super(editCharacterTraitNumberCurrent, self).__init__(config, session, min_access_level=2, accepted_input = {
            'traitId': (MUST, validator_trait_number),
            'charId': (MUST, validator_character),
            'newValue': (MUST, validator_positive_integer),   
        })
    @web_security(sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId'))))
    def mGET(self):
        lid = getLanguage(self.session, dbm)      
        issuer = self.session.discord_userid
        character = self.input_data['charId']  
        trait_id = self.input_data['traitId']
        new_val = self.input_data['newValue']
        charId = character['id']

        trait = dbm.getTrait(charId, trait_id)

        if trait['pimp_max']==0 and trait['trackertype']==0:
            raise WebException(f"Current value cannot be modified")

        if new_val > trait['max_value'] and trait['trackertype'] != 3:
            raise WebException("Value too large", 400)
        
        dbm.db.update("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait_id, pc=character['id']), cur_value = new_val)
        dbm.log(issuer, character['id'], trait_id, ghostDB.LogType.CUR_VALUE, new_val, trait['cur_value'], "web edit")
        return dbm.getTrait_LangSafe(charId, trait_id, lid)
Example #3
0
class editCharacterReassign(APIResponse): #textbased
    def __init__(self):
        super(editCharacterReassign, self).__init__(config, session, min_access_level=2, accepted_input = {
            'userId': (MUST, validator_bot_user), 
            'charId': (MUST, validator_character),
        })
    @web_security(sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId'))))
    def mGET(self):
        character = self.input_data['charId']
        charId = character['id']
        user = self.input_data['userId']
        userId = user['userid']

        dbm.reassignCharacter(charId, userId)
        return user
Example #4
0
class editCharacterTraitText(APIResponse): #textbased
    def __init__(self):
        super(editCharacterTraitText, self).__init__(config, session, min_access_level=2, accepted_input = {
            'traitId': (MUST, validator_trait_textbased), 
            'charId': (MUST, validator_character),
            'newValue': (MUST, validator_str_range(1, 50)),   
        })
    @web_security(sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId'))))
    def mGET(self):
        issuer = self.session.discord_userid
        character = self.input_data['charId']
        trait_id = self.input_data['traitId']
        new_val = self.input_data['newValue']
        charId = character['id']
        
        trait = dbm.getTrait(charId, trait_id)
        
        dbm.db.update("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait_id, pc=character['id']), text_value = new_val)
        dbm.log(issuer, character['id'], trait_id, ghostDB.LogType.TEXT_VALUE, new_val, trait['text_value'], "web edit")
        return dbm.getTrait_LangSafe(charId, trait_id, getLanguage(self.session, dbm))
Example #5
0
class editCharacterTraitRemove(APIResponse): #textbased
    def __init__(self):
        super(editCharacterTraitRemove, self).__init__(config, session, min_access_level=2, accepted_input = {
            'traitId': (MUST, validator_trait), 
            'charId': (MUST, validator_character),
        })
    @web_security(sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId'))))
    def mGET(self):
        issuer = self.session.discord_userid
        character = self.input_data['charId']
        trait_id = self.input_data['traitId']
        charId = character['id']
        
        trait = dbm.getTrait(charId, trait_id)

        updated_rows = dbm.db.delete("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait['id'], pc=character['id']))
        if trait['textbased']:
            dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.DELETE, "", trait['text_value'], "web edit")
        else:
            dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.DELETE, "", f"{trait['cur_value']}/{trait['max_value']}", "web edit")
            
        return {"trait": trait_id}
    async def before_invoke_command_security(instance: gb.GreedyGhostCog,
                                             ctx: commands.Context):
        security_check_class = security_item
        if len(additional_security_items):
            security_check_class = sec.AND(security_item,
                                           *additional_security_items)

        if not issubclass(security_check_class, sec.CommandSecurity):
            raise BotSecurityCheckException(
                f"Type {security_check_class} is not a {sec.CommandSecurity} object"
            )

        security_check_instance = None

        bot_instance: gb.GreedyGhost = None
        if isinstance(instance, gb.GreedyGhostCog):
            bot_instance = instance.bot
        elif isinstance(
                instance, gb.GreedyGhost
        ):  # should never happen but will save us if we define a command in the main bot instead of cogs
            bot_instance = instance

        if (not bot_instance is None):
            security_check_instance = security_check_class(
                ctx, **security_options)
        else:
            raise BotSecurityCheckException(
                f"Command security is supported only for commands defined in a GreedyGhostCog. Provided object type: {type(instance)}"
            )

        security_pass, security_comment = security_check_instance.checkSecurity(
            *ctx.args, **ctx.kwargs)
        if not security_pass:
            raise BotSecurityCheckException(
                "string_error_permission_denied",
                (bot_instance.formatException(ctx, security_comment), ))
Example #7
0
class GreedyGhostCog_PCMod(gb.GreedyGhostCog):

    @commands.group(brief='Gestione personaggi')
    @commands.before_invoke(gs.command_security(gs.basicRegisteredUser))
    async def pgmod(self, ctx: commands.Context):
        if ctx.invoked_subcommand is None:
            response = utils.discord_text_format_mono('Azioni disponibili:\n\n' + '\n'.join(list(map(lambda k: f'{k} - {pgmod_help[k][1]}', pgmod_help))))
            await self.bot.atSend(ctx, response)

    @pgmod.command(name = 'create', brief = "Crea un personaggio", description = create_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.OR(sec.IsStoryteller, sec.genIsSelf(optional_target_user = 3))))))
    async def create(self, ctx : commands.Context, character_id: gc.GreedyShortIdConverter, user: gc.RegisteredUserConverter, name, *args):
        fullname = " ".join(list([name]+list(args)))

        self.bot.dbm.newCharacter(character_id, fullname, user['userid'])
        await self.bot.atSend(ctx, f'Il personaggio {fullname} è stato inserito!')

    @pgmod.command(name = 'link', brief = "Aggiunge un personaggio ad una cronaca", description = link_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genIsChronicleStoryteller(target_chronicle = 3)))))
    async def link(self, ctx: commands.Context, character: gc.CharacterConverter, chronicle: gc.ChronicleConverter):
        is_linked, _ = self.bot.dbm.isCharacterLinkedToChronicle(character['id'], chronicle['id'])
        if is_linked:
            await self.bot.atSend(ctx, f"C'è già un'associazione tra {character['fullname']} e {chronicle['name']}")
        else:
            self.bot.dbm.db.insert("ChronicleCharacterRel", chronicle=chronicle['id'], playerchar=character['id'])
            await self.bot.atSend(ctx, f"{character['fullname']} ora gioca a {chronicle['name']}")

    @pgmod.command(name = 'unlink', brief = "Disassocia un personaggio da una cronaca", description = unlink_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genIsChronicleStoryteller(target_chronicle = 3)))))
    async def unlink(self, ctx: commands.Context, character: gc.CharacterConverter, chronicle: gc.ChronicleConverter):
        is_linked, _ = self.bot.dbm.isCharacterLinkedToChronicle(character['id'], chronicle['id'])
        if is_linked:
            self.bot.dbm.db.delete("ChronicleCharacterRel", where = 'playerchar=$playerchar and chronicle=$chronicleid', vars=dict(chronicleid=chronicle['id'], playerchar=character['id']))
            await self.bot.atSend(ctx, f"{character['fullname']} ora non gioca più a  {chronicle['name']}")
        else:
            await self.bot.atSend(ctx, f"Non c\'è un\'associazione tra {character['fullname']} e {chronicle['name']}")

    @pgmod.command(name = 'addt', brief = "Aggiunge tratto ad un personaggio", description = addt_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genCanEditCharacter(target_character=2)))))
    async def addt(self, ctx: gb.GreedyContext, character: gc.CharacterConverter, trait: gc.TraitConverter, value, *args):
        issuer = str(ctx.message.author.id)
        
        try:
            lid = ctx.getLID()
            ptrait = self.bot.dbm.getTrait_LangSafe(character['id'], trait['id'], lid)
            raise gb.BotException(f"{character['fullname']} ha già il tratto {ptrait['name']} ")
        except ghostDB.DBException:
            pass
        
        ttype = self.bot.dbm.db.select('TraitType', where='id=$id', vars=dict(id=trait['traittype']))[0]
        val = None
        if ttype['textbased']:
            val = " ".join([value]+list(args))
            self.bot.dbm.db.insert("CharacterTrait", trait=trait['id'], playerchar=character['id'], cur_value = 0, max_value = 0, text_value = val, pimp_max = 0)
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.TEXT_VALUE, val, '', ctx.message.content)
        else:
            val = int(value)
            pimp = 6 if trait['traittype'] in ['fisico', 'sociale', 'mentale'] else 0
            self.bot.dbm.db.insert("CharacterTrait", trait=trait['id'], playerchar=character['id'], cur_value = val, max_value = val, text_value = "", pimp_max = pimp)
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.MAX_VALUE, val, '', ctx.message.content)
        
        await self.bot.atSend(ctx, f"{character['fullname']} ora ha {trait['name']} {val}")

    @pgmod.command(name = 'modt', brief = "Modifica un tratto di un personaggio", description = modt_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genCanEditCharacter(target_character = 2)))))
    async def modt(self, ctx: gb.GreedyContext, character: gc.CharacterConverter, trait: gc.TraitConverter, value, *args):
        issuer = str(ctx.message.author.id)
        
        chartrait = self.bot.dbm.getTrait_LangSafe(character['id'], trait['id'], ctx.getLID())
                
        ttype = self.bot.dbm.db.select('TraitType', where='id=$id', vars=dict(id=trait['traittype']))[0]
        val = None
        if ttype['textbased']:
            val = " ".join([value]+list(args))
            self.bot.dbm.db.update("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait['id'], pc=character['id']), text_value = val)
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.TEXT_VALUE, val, chartrait['text_value'], ctx.message.content)
        else:
            val = int(value)
            self.bot.dbm.db.update("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait['id'], pc=character['id']), cur_value = val, max_value = val)
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.MAX_VALUE, val, chartrait['max_value'], ctx.message.content)
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.CUR_VALUE, val, chartrait['cur_value'], ctx.message.content)
        
        await self.bot.atSend(ctx, f"{character['fullname']} ora ha {trait['name']} {val}")
    
    
    @pgmod.command(name = 'rmt', brief = "Rimuovi un tratto ad un personaggio", description = rmt_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genCanEditCharacter(target_character = 2)))))
    async def rmt(self, ctx: gb.GreedyContext, character: gc.CharacterConverter, trait: gc.TraitConverter):
        issuer = str(ctx.message.author.id)
        chartrait = self.bot.dbm.getTrait_LangSafe(character['id'], trait['id'], ctx.getLID())
        ttype = self.bot.dbm.db.select('TraitType', where='id=$id', vars=dict(id=trait['traittype']))[0]
        
        updated_rows = self.bot.dbm.db.delete("CharacterTrait", where='trait = $trait and playerchar = $pc', vars=dict(trait=trait['id'], pc=character['id']))
        if ttype['textbased']:
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.DELETE, "", chartrait['text_value'], ctx.message.content)
        else:
            self.bot.dbm.log(issuer, character['id'], trait['id'], ghostDB.LogType.DELETE, "", f"{chartrait['cur_value']}/{chartrait['max_value']}", ctx.message.content)
        if updated_rows > 0:
            await self.bot.atSend(ctx, f"Rimosso {trait['name']} da {character['fullname']} ({updated_rows})")
        else:
            await self.bot.atSend(ctx, f"Nessun tratto rimosso")

    @pgmod.command(name = 'reassign', brief = pgmod_help["reassign"][1], description = pgmod_help["reassign"][0])
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genCanEditCharacter(target_character = 2)))))
    async def reassign(self, ctx: commands.Context, character: gc.CharacterConverter, user: gc.RegisteredUserConverter):
        self.bot.dbm.reassignCharacter(character['id'], user['userid'])        
        await self.bot.atSendLang(ctx, "string_msg_character_reassigned_to_user", character["fullname"], user['name'])
Example #8
0
class GreedyGhostCog_Session(gb.GreedyGhostCog):
    @commands.group(
        name='session',
        brief='Controlla le sessioni di gioco',
        description=
        "Le sessioni sono basate sui canali: un canale può ospitare una sessione alla volta, ma la stessa cronaca può avere sessioni attive in più canali."
    )
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def session(self, ctx: commands.Context):
        if ctx.invoked_subcommand is None:
            sessions = self.bot.dbm.db.select(
                'GameSession',
                where='channel=$channel',
                vars=dict(channel=ctx.channel.id))
            if len(sessions):
                chronicle = self.bot.dbm.db.select(
                    'Chronicle',
                    where='id=$chronicle',
                    vars=dict(chronicle=sessions[0]['chronicle']))
                cn = chronicle[0]['name']
                await self.bot.atSend(ctx, f"Sessione attiva: {cn}")
            else:
                await self.bot.atSend(
                    ctx, "Nessuna sessione attiva in questo canale!")

    @session.command(
        name='start',
        brief='Inizia una sessione',
        description=
        '.session start <nomecronaca>: inizia una sessione per <nomecronaca> (richiede essere admin o storyteller della cronaca da iniziare) (richiede essere admin o storyteller della cronaca da iniziare)'
    )
    @commands.before_invoke(
        gs.command_security(
            sec.OR(
                sec.IsAdmin,
                sec.AND(
                    sec.OR(sec.IsActiveOnGuild,
                           sec.IsPrivateChannelWithRegisteredUser),
                    sec.genIsChronicleStoryteller(target_chronicle=2)))))
    async def start(self, ctx: commands.Context,
                    chronicle: gc.ChronicleConverter):
        chronicleid = chronicle['id'].lower()
        response = ''

        sessions = self.bot.dbm.db.select('GameSession',
                                          where='channel=$channel',
                                          vars=dict(channel=ctx.channel.id))
        if len(sessions):
            response = f"C'è già una sessione in corso in questo canale: {sessions[0]['chronicle']}"
        else:
            self.bot.dbm.db.insert('GameSession',
                                   chronicle=chronicleid,
                                   channel=ctx.channel.id)
            response = f"Sessione iniziata per la cronaca {chronicle['name']}"
            # TODO lista dei pg?
            # TODO notifica i giocatori di pimp attivi

        await self.bot.atSend(ctx, response)

    @session.command(
        name='list',
        brief='Elenca le sessioni aperte',
        description=
        'Elenca le sessioni aperte. richiede di essere admin o storyteller')
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def session_list(self, ctx: commands.Context):
        sessions = self.bot.dbm.db.select('GameSession').list()
        channels = []
        lines = []
        for s in sessions:
            try:
                ch = await self.bot.fetch_channel(int(s['channel']))
                channels.append(ch)
            except discord.errors.Forbidden as e:
                lines.append(f"**{s['chronicle']}** in: UNKNOWN")
                channels.append(None)
        #pvt = 0
        for session, channel in zip(sessions, channels):
            if isinstance(channel, discord.abc.GuildChannel):
                lines.append(
                    f"**{session['chronicle']}** in: {channel.guild.name}/{channel.category}/{channel.name}"
                )
            elif isinstance(channel, discord.abc.PrivateChannel):
                lines.append(
                    f"**{session['chronicle']}** in un canale privato")
        if not len(lines):
            lines.append("Nessuna!")
        response = "Sessioni attive:\n" + ("\n".join(lines))
        await self.bot.atSend(ctx, response)

    @session.command(
        name='end',
        brief='Termina la sessione corrente',
        description=
        'Termina la sessione corrente. Richiede di essere admin o storyteller della sessione in corso.'
    )
    @commands.before_invoke(
        gs.command_security(
            sec.OR(
                sec.IsAdmin,
                sec.AND(
                    sec.OR(sec.IsActiveOnGuild,
                           sec.IsPrivateChannelWithRegisteredUser),
                    sec.CanEditRunningSession))))
    async def end(self, ctx: commands.Context):
        response = ''

        n = self.bot.dbm.db.delete('GameSession',
                                   where='channel=$channel',
                                   vars=dict(channel=ctx.channel.id))
        if n:
            response = f'sessione terminata'
        else:  # non dovrebbe mai accadere
            response = f'Non c\'è una sessione aperta in questo canale'

        await self.bot.atSend(ctx, response)
Example #9
0
class GreedyGhostCog_GMadm(gb.GreedyGhostCog):
        
    @commands.group(brief='Gestione sistema di gioco')
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def gmadm(self, ctx: commands.Context):
        if ctx.invoked_subcommand is None:
            response = utils.discord_text_format_mono('Azioni disponibili:\n\n' + '\n'.join(list(map(lambda k: f'{k} - {gmadm_help[k][1]}', gmadm_help))))
            await self.bot.atSend(ctx, response)

    @gmadm.command(name = 'listChronicles', brief = gmadm_help['listChronicles'][1], description = listChronicles_description)
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def listChronicles(self, ctx: commands.Context):

        query = """
    SELECT cr.id as cid, cr.name as cname, p.name as pname
    FROM Chronicle cr
    JOIN StoryTellerChronicleRel stcr on (cr.id = stcr.chronicle)
    JOIN People p on (stcr.storyteller = p.userid)
"""
        results = self.bot.dbm.db.query(query)
        if len(results) == 0:
            await self.bot.atSend(ctx, "Nessuna cronaca trovata!")
            return

        chronicles = {}
        crst = {}
        for c in results:
            chronicles[c['cid']] = c['cname']
            if not c['cid'] in crst:
                crst[c['cid']] = []
            crst[c['cid']].append(c['pname'])

        await self.bot.atSend(ctx, "Cronache:\n" + "\n".join(list(map(lambda x: f"**{chronicles[x]}** ({x}) (storyteller: {', '.join(crst[x])})", chronicles))))

    @gmadm.command(name = 'newChronicle', brief = gmadm_help['newChronicle'][1], description = newChronicle_description)
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def newChronicle(self, ctx: commands.Context, shortname: gc.GreedyShortIdConverter,  *args):
        if len(args) == 0:
            self.bot.atSend(ctx, newChronicle_description)
            return 

        fullname = " ".join(list(args)) # squish

        issuer = str(ctx.message.author.id)

        # todo existence
        t = self.bot.dbm.db.transaction()
        try:
            self.bot.dbm.db.insert("Chronicle", id=shortname, name = fullname)
            self.bot.dbm.db.insert("StoryTellerChronicleRel", storyteller=issuer, chronicle=shortname)
        except:
            t.rollback()
            raise
        else:
            t.commit()
            issuer_user = await self.bot.fetch_user(issuer)
        
        await self.bot.atSend(ctx, f"Cronaca {fullname} inserita ed associata a {issuer_user}")

    @gmadm.command(name = 'newTrait', brief = gmadm_help['newTrait'][1], description = newTrait_description)
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def newTrait(self, ctx: commands.Context, traitid: gc.GreedyShortIdConverter, traittype: gc.TraitTypeConverter, tracktype: gc.TrackerTypeConverter, std: gc.NoYesConverter, *args):
        if len(args) == 0:
            await self.bot.atSend(ctx, newTrait_description)
            return
                
        istrait, _ = self.bot.dbm.validators.getValidateTrait(traitid).validate()
        if istrait:
            raise gb.BotException(f"Il tratto {traitid} esiste già!")
        
        traittypeid = traittype['id']

        traitname = " ".join(args)

        response = ""
        t = self.bot.dbm.db.transaction()
        try:
            self.bot.dbm.db.insert("Trait", id = traitid, name = traitname, traittype = traittypeid, trackertype = tracktype, standard = std, ordering = 1.0)
            # we insert it in all available languages and we assume that it will be translated later:
            # better have it in the wrong language than not having it at all
            self.bot.dbm.db.query(query_addTraitLangs, vars = dict(traitid=traitid, traitname=traitname))
            response = f'Il tratto {traitname} è stato inserito'
            if std:
                self.bot.dbm.db.query(query_addTraitToPCs, vars = dict(traitid=traitid))
                response +=  f'\nIl nuovo tratto standard {traitname} è stato assegnato ai personaggi!'
        except:
            t.rollback()
            raise
        else:
            t.commit()

        await self.bot.atSend(ctx, response)

    @gmadm.command(name = 'updt', brief = gmadm_help['updt'][1], description = updt_description)
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def updt(self, ctx: gb.GreedyContext, old_traitid: gc.GreedyShortIdConverter, new_traitid: gc.GreedyShortIdConverter, traittype: gc.TraitTypeConverter, tracktype: gc.TrackerTypeConverter, std: gc.NoYesConverter, *args):    
        if len(args) == 0:
            await self.bot.atSend(ctx, newTrait_description)
            return
        
        istrait, old_trait = self.bot.dbm.validators.getValidateTrait( old_traitid).validate()
        if not istrait:
            raise gb.BotException(f"Il tratto {old_traitid} non esiste!")
        
        istrait, new_trait = self.bot.dbm.validators.getValidateTrait(new_traitid).validate()
        if istrait and (old_traitid!=new_traitid):
            raise gb.BotException(f"Il tratto {new_traitid} esiste già!")

        traittypeid = traittype['id']

        traitname = " ".join(list(args))
        
        response = f'Il tratto {traitname} è stato aggiornato'
        t = self.bot.dbm.db.transaction()
        try:
            self.bot.dbm.db.update("Trait", where= 'id = $oldid' , vars=dict(oldid = old_traitid), id = new_traitid, name = traitname, traittype = traittypeid, trackertype = tracktype, standard = std, ordering = 1.0)
            # now we update the language description, but only of the current language
            self.bot.dbm.db.update("LangTrait", where= 'traitId = $traitid and langId = $lid' , vars=dict(traitid=new_traitid, lid = ctx.getLID()), traitName = traitname)
            if std and not old_trait['standard']:
                self.bot.dbm.db.query(query_addTraitToPCs_safe, vars = dict(traitid=new_traitid))
                response +=  f'\nIl nuovo talento standard {traitname} è stato assegnato ai personaggi!'
            elif not std and old_trait['standard']:
                self.bot.dbm.db.query("""
    delete from CharacterTrait
    where trait = $traitid and max_value = 0 and cur_value = 0 and text_value = '';
    """, vars = dict(traitid=new_traitid))
                response += f'\nIl talento {traitname} è stato rimosso dai personaggi che non avevano pallini'
        except:
            t.rollback()
            raise
        else:
            t.commit()

        await self.bot.atSend(ctx, response)

    @gmadm.command(name = 'link', brief = gmadm_help['link'][1], description = link_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genIsChronicleStoryteller(target_chronicle=2)))))
    async def link(self, ctx: commands.Context, chronicle: gc.ChronicleConverter, storyteller: gc.StorytellerConverter = None):
        issuer = str(ctx.message.author.id)
        
        chronid = chronicle['id']

        target_st = None
        if storyteller == None:
            storyteller = await gc.StorytellerConverter().convert(ctx, issuer)
        target_st = storyteller['userid']
        
        t_stc, _ = self.bot.dbm.isChronicleStoryteller(target_st, chronid)
        if t_stc:
            raise gb.BotException(f"L'utente selezionato è già Storyteller per {chronid}")  

        # link
        self.bot.dbm.db.insert("StoryTellerChronicleRel", storyteller=target_st, chronicle=chronid)
        await self.bot.atSend(ctx, f"Cronaca associata")

    @gmadm.command(name = 'unlink', brief = gmadm_help['unlink'][1], description = unlink_description)
    @commands.before_invoke(gs.command_security(sec.OR(sec.IsAdmin, sec.AND( sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser), sec.genIsChronicleStoryteller(target_chronicle=2), sec.genIsSelf(optional_target_user=3)))))
    async def unlink(self, ctx: context.Context, chronicle: gc.ChronicleConverter, storyteller: gc.StorytellerConverter = None):

        issuer = str(ctx.message.author.id)
        chronid = chronicle['id']
        
        target_st = None
        if storyteller == None:
            storyteller = await gc.StorytellerConverter().convert(ctx, issuer)
        target_st = storyteller['userid'] 

        # link
        n = self.bot.dbm.db.delete('StoryTellerChronicleRel', where='storyteller=$storyteller and chronicle=$chronicle', vars=dict(storyteller=target_st, chronicle=chronid))
        if n:
            await self.bot.atSend(ctx, f"Cronaca disassociata")
        else:
            await self.bot.atSend(ctx, f"Nessuna cronaca da disassociare")

    @gmadm.command(name = 'name', brief = gmadm_help['name'][1], description = name_description)
    @commands.before_invoke(gs.command_security(sec.IsAdmin))
    async def name(self, ctx: commands.Context, user: gc.RegisteredUserConverter):
        
        target_st = user['userid'] 
        name = user['name']

        t_st, _ = self.bot.dbm.validators.getValidateBotStoryTeller(target_st).validate()
        if t_st:
            raise gb.BotException(f"L'utente selezionato è già uno storyteller")
        
        self.bot.dbm.db.insert("Storyteller",  userid=target_st)
        await self.bot.atSend(ctx, f"{name} ora è Storyteller")
        
    @gmadm.command(name = 'unname', brief = gmadm_help['unname'][1], description = unname_description)
    @commands.before_invoke(gs.command_security(sec.IsAdmin))
    async def unname(self, ctx: commands.Context, storyteller: gc.StorytellerConverter):

        target_st = storyteller['userid'] 
        name = storyteller['name']
        
        n = self.bot.dbm.unnameStoryTeller(target_st)
        if n:
            await self.bot.atSend(ctx, f"{name} non è più Storyteller")
        else:
            await self.bot.atSend(ctx, f"Nessuna modifica fatta")
    
    @gmadm.command(name = 'traittypes', brief = gmadm_help['traittypes'][1], description = traittypes_description)
    @commands.before_invoke(gs.command_security(gs.basicStoryTeller))
    async def traittypes(self, ctx: commands.Context):
        
        ttypesl = self.bot.dbm.db.select('TraitType', what = "id, name").list()
        response = "Tipi di tratto: \n"
        response += "\n".join(list(map(lambda x : f"\t**{x['id']}**: {x['name']}", ttypesl)))
        
        await self.bot.atSend(ctx, response)
Example #10
0
 def mGET(self):
     return int(check_web_security(self, sec.OR(sec.IsAdmin, sec.AND( sec.IsUser, sec.genCanEditCharacter(target_character = 'charId')))))
from typing import Any, Callable

from greedy_components import greedyBase as gb
from discord.ext import commands
from support import security as sec
from lang import lang as lng


class BotSecurityCheckException(lng.LangSupportException,
                                commands.CommandError):
    pass


basicRegisteredUser: type[sec.CommandSecurity] = sec.OR(
    sec.IsAdmin, sec.AND(sec.IsUser, sec.IsActiveOnGuild),
    sec.IsPrivateChannelWithRegisteredUser)
basicStoryTeller: type[sec.CommandSecurity] = sec.OR(
    sec.IsAdmin,
    sec.AND(
        sec.IsStoryteller,
        sec.OR(sec.IsActiveOnGuild, sec.IsPrivateChannelWithRegisteredUser)))


def command_security(security_item: type[sec.CommandSecurity] = sec.NoCheck,
                     *additional_security_items: type[sec.CommandSecurity],
                     **security_options):
    """ Add security checks to a command with before_invoke, needs CommandSecurity objects as parameters
    If all the CommandSecurity items pass their checks, then the command executes.
    
    Example
    ---------