Example #1
0
class Device:
    class EventError(Exception):
        pass

    def __init__(self, path: str, name: str, host: str, port: int):
        """ Constructor """
        self._name = name
        self.host = host
        self.port = port
        self.datadir = os.path.join(path, 'data')
        if not os.path.exists(self.datadir):
            os.mkdir(self.datadir)
        db_path = os.path.join(self.datadir, f'device_{self._name}.sqlite3')
        self.lock_db = BoundedSemaphore(1)
        self.db = sqlite3.connect(db_path)

    @property
    def name(self):
        return f'[DEV {self._name}]'

    @contextmanager
    def cursor(self):
        """ Cursor decorator with database lock """
        cursor = self.db.cursor()
        try:
            self.lock_db.acquire()
            yield cursor
            self.db.commit()
        finally:
            # noinspection PyBroadException
            try:
                if self.lock_db.locked():
                    self.lock_db.release()
            except Exception:
                pass
            # noinspection PyBroadException
            try:
                cursor.close()
            except Exception:
                pass

    def run(self):
        """ Run """
        raise NotImplementedError()

    def event(self, ts: datetime, value: TValue, retries: int = 0) -> int:
        """ Notify event """
        raise NotImplementedError()

    def _value(self, value: str) -> TValue:
        """ Convert value """
        raise NotImplementedError()
Example #2
0
class _LeakySemaphore(object):
    def __init__(self, value = 1, maxSeconds = 10):
        self._semaphore = BoundedSemaphore(value)
        self._maxSeconds = maxSeconds
        self._timer = None
        self._leaked = 0
        self._stopped = False

    def _leak(self):
        sleep(self._maxSeconds)
        self._leaked += 1
        self._semaphore.release()

    @property
    def inUse(self):
        return self._semaphore._initial_value - self.semaphore.counter

    @property
    def waiting(self):
        return len(self._semaphore._links)

    def release(self):
        if self._stopped:
            return
        if self._leaked > 0:
            self._leaked -= 1
        else:
            self._semaphore.release()

    def stop(self):
        self._stopped = True

        if self._timer is not None:
            self._timer.kill(block = False)
            self._timer = None

        while self.waiting > 0:
            self._semaphore.release()
            sleep(0.1)

    def acquire(self):
        if self._stopped:
            return
        if self._semaphore.locked() and not self._timer:
            self._timer = spawn(self._leak)
        self._semaphore.acquire(blocking = True, timeout = None)
        if self._timer is not None:
            self._timer.kill(block = False)
            self._timer = None
            if self.waiting > 0:
                self._timer = spawn(self._leak)
Example #3
0
class _LeakySemaphore(object):
    def __init__(self, value=1, maxSeconds=10):
        self._semaphore = BoundedSemaphore(value)
        self._maxSeconds = maxSeconds
        self._timer = None
        self._leaked = 0
        self._stopped = False

    def _leak(self):
        sleep(self._maxSeconds)
        self._leaked += 1
        self._semaphore.release()

    @property
    def inUse(self):
        return self._semaphore._initial_value - self.semaphore.counter

    @property
    def waiting(self):
        return len(self._semaphore._links)

    def release(self):
        if self._stopped:
            return
        if self._leaked > 0:
            self._leaked -= 1
        else:
            self._semaphore.release()

    def stop(self):
        self._stopped = True

        if self._timer is not None:
            self._timer.kill(block=False)
            self._timer = None

        while self.waiting > 0:
            self._semaphore.release()
            sleep(0.1)

    def acquire(self):
        if self._stopped:
            return
        if self._semaphore.locked() and not self._timer:
            self._timer = spawn(self._leak)
        self._semaphore.acquire(blocking=True, timeout=None)
        if self._timer is not None:
            self._timer.kill(block=False)
            self._timer = None
            if self.waiting > 0:
                self._timer = spawn(self._leak)
Example #4
0
class GearSheetPlugin(Plugin):
    session = ""
    conn = None
    WEAPON_TALENTS = 'weapontalents'
    PLAYER_TALENTS = 'playertalents'
    GEAR_TALENTS = 'geartalents'
    GEAR_SETS = 'gearsets'
    WEAPONS = 'weapons'
    WEAPON_MODS = 'weaponmods'
    EXOTIC_GEARS = 'exoticgears'
    GEAR_ATTRIBUTES = 'gearattributes'

    names = {}
    vendor_names = {}
    logger = None
    lock = None

    def __init__(self, bot, config):
        super().__init__(bot, config)

        print('Logging in to backend api...')
        login_params = json.dumps({'username': '******', 'password': '******', 'appcode': 'gearsheet'})
        conn = http.client.HTTPConnection("localhost:9000")

        conn.request('POST', '/login', login_params, {'Content-Type': 'application/json'})
        login_response = conn.getresponse()
        login_response = json.loads(login_response.read().decode('utf-8'))

        if login_response['result'] != 'ok':
            print("Login to baasbox failed")
            return

        print('Login successful.')
        self.session = login_response['data']["X-BB-SESSION"]

        # get a list of all indexed names
        params = urllib.parse.urlencode({'fields': 'name'})
        conn.request('GET', '/document/indexes?%s' % params, headers={'X-BB-SESSION': self.session})
        res = json.loads(conn.getresponse().read().decode('utf-8'))
        self.names = {i['name'] for i in res['data']}

        conn.close()

        vendors_param = { "fields": "name" }
        response = requests.get(BACKEND_HOST + '/document/vendors-indexes', params=vendors_param, headers={SESSION_HEADER: self.session})
        self.vendor_names = {i['name'] for i in response.json()['data']}

        # init logging
        self.logger = logging.getLogger('gearsheet_bot')
        self.logger.setLevel(logging.INFO)

        fh = logging.FileHandler('access.log')
        fh.setLevel(logging.INFO)

        formatter = logging.Formatter('%(asctime)s - %(name)s - %(message)s')
        fh.setFormatter(formatter)

        self.logger.addHandler(fh)
        
        self.lock = BoundedSemaphore(1)

        #print(self.state.guilds)

    #in a plugin class
    @Plugin.listen('Ready')
    def on_ready(self, event):
        self.client.update_presence(Status.online, Game(type=GameType.default, name='!help for guide'))

    @Plugin.command('help')
    def command_help(self, event):
        skip = { 264445053596991498 : "discord bot list"}
                                
        if event.guild.id in skip.keys():
            return
        
        self.log_it(event, "", "help")
        event.msg.reply('Usage Guide <https://docs.google.com/document/d/1G1d1oj0qDbv6yf7EOEkGAHN40OqsdkXRrxCHo_3QC2w/view>')

    @Plugin.command('ping')
    def command_ping(self, event):
        event.msg.reply("Pong!")

    @Plugin.command('servers')
    def command_servers(self, event):
        if event.author.id in [195168390476726272]:
            event.msg.reply("I am currently installed on %s servers" % len(self.state.guilds))
    
    @Plugin.command('nicknames')
    def command_nicknames(self, event):
        self.log_it(event, "", "nicknames")
        event.msg.reply("<https://goo.gl/Brh1TF>")

    @Plugin.command('add')
    def command_add(self, event):
        pass

    def log_it(self, event, param, command):
        if event.author.id not in [195168390476726272]:
            self.logger.info("%s - %s - %s - %s - %s" % (command, str(event.author).replace(" ", "_"), event.guild.name.replace(" ", "_"), event.guild.id, param))

    @Plugin.command('g')
    @Plugin.command('s')
    @Plugin.command('sheet')
    @Plugin.command('gearsheet')
    def command_talents(self, event):
        if len(event.args) > 0:
            param = ' '.join(event.args).lower()

            if param == 'help':
                help_text = '''I can only perform simple searches for **The Division** related items\n
Example: to find out what *Responsive* talent does, use `!gearsheet responsive`\n
Popular community nicknames for items are also supported.\n
**PRO TIP**: `!sheet responsive` will also work.

My reddit thread: <https://goo.gl/638vpi>.

**Credit** to @Pfftman#6620 | /u/pfftman | PSN: pfftman'''

                self.log_it(event, param, "gearsheet")
                event.msg.reply(help_text)
                return

            if param in util.aliases.keys():
                param = util.aliases[param].lower()
            
            if param in scopes and param != 'weapons':
                self.log_it(event, param, "gearsheet")
                query = {
                    'fields': 'name',
                    'orderBy': 'name'
                }
                names = requests.get(BACKEND_HOST + "/document/%s" % param, query, headers={SESSION_HEADER: self.session}).json()
                # print(names)
                name_list = ['`' + i["name"] + '`' for i in names["data"]]

                event.msg.reply('there are **%s items**' % len(name_list))
                event.msg.reply(",  ".join(name_list))

                return
            
            # start_time = time.time()
            conn = http.client.HTTPConnection("localhost:9000")
            conn.request('GET', '/plugin/bot.index?%s' % (urllib.parse.urlencode({"param": param})),
                            headers={'X-BB-SESSION': self.session})

            response = conn.getresponse().read().decode('utf-8')
            conn.close()
            # time_diff = time.time() - start_time

            
            self.log_it(event, param, "gearsheet")

            response = json.loads(response)
            if response['result'] != 'ok':
                matches = [("**%s**" % i).title() for i in self.names if fuzz.partial_ratio(param, i) > 80]

                if len(matches) > 0:
                    match_str = "this %s" % ', '.join(matches) if len(matches) == 1 else \
                        "any of these %s" % ', '.join(matches)
                    text = "Did you mean to search for %s?" % \
                           match_str
                    event.msg.reply('%s' % text)
                else:
                    event.msg.reply('```item not found```')

                return

            for item in response['data']:
                collection_name = item['@class']

                embed = None
                if collection_name == self.WEAPON_TALENTS:
                    embed = self.render_weapon_talent(item)
                elif collection_name == self.PLAYER_TALENTS:
                    embed = self.render_player_talent(item)
                elif collection_name == self.GEAR_TALENTS:
                    embed = self.render_gear_talent(item)
                elif collection_name == self.GEAR_SETS:
                    embed = self.render_gearset(item)
                elif collection_name == self.WEAPONS:
                    embed = self.render_weapon(item)
                elif collection_name == self.WEAPON_MODS:
                    embed = self.render_weapon_mods(item)
                elif collection_name == self.EXOTIC_GEARS:
                    embed = self.render_exotic_gear(item)
                elif collection_name == self.GEAR_ATTRIBUTES:
                    embed = self.render_gear_attribute(item)

                event.msg.reply(embed=embed)

    @Plugin.command('v')
    @Plugin.command('vendors')
    @Plugin.command('vendor')
    def command_vendors(self, event):
        if len(event.args) > 0:
            param = ' '.join(event.args).lower()
            splitted = param.strip().split(" with ")

            # handle requests from weapons in plural form
            if splitted[0] in weapon_types:
                temp = splitted[0]
                splitted[0] = temp[:-1]
            
            if event.author.id not in [195168390476726272]:
                self.log_it(event, param, "vendors")

            # routines related to updatee
            if param.strip(' ') == 'update': #pfft              #ruben              #noots              #ahmad
                if event.author.id in { 195168390476726272, 177627571700105217, 196408555132289024, 99511296604520448 }:
                    self.handle_update(event)
                else:
                    event.msg.reply("Haha! no")
                return
            
            if param.strip(' ') == 'status':
                reply = self.render_status_command()
                event.msg.reply(embed=reply)
                return
            
            arg = None
            param_obj = None
            
            for i, item in enumerate(splitted): # check if there is already a nickname
                # start with the vendor aliases and fallback to the gearsheet aliases
                if item in util.vendor_aliases.keys():
                    splitted[i] = util.vendor_aliases[item].lower()
            
            # determine the kind of request to send to the server
            query = splitted[0]    
            if len(splitted) == 1: # this block takes care of args without 'with'
                param_obj = {
                    "param": splitted[0],
                    "has_arg": False
                }
            elif len(splitted) >= 2:
                arg = splitted[1]
                param_obj = {
                    "param": splitted[0],
                    "has_arg": True,
                    "arg": splitted[1] # take only one argument
                }
            else:
                event.msg.reply('```You shouldn\'t be able to get here. Yet.. ```')
                return

            header = {SESSION_HEADER: self.session}
            response = requests.get(BACKEND_HOST + '/plugin/vendors.index', params=param_obj, headers=header)

            if response.json()['result'] != 'ok': # item not found in vendors list
                # try to determine if it was a bad input from user or an item that doesn't exist
                self.reply_item_not_found(query, event)
                return
            
            data = remove_duplicates(response.json()["data"])
            data = sorted(data, key=lambda item: item['name'])
            embed = None

            if len(data) > 1:
                embed = self.render_multiple_items(data)
            else:
                for item in data:
                    collection = item['@class']

                    if collection == "vendors-%s" % VENDOR_WEAPONS:
                        embed = self.render_vendor_weapon(item)
                    elif collection == get_collection_name(VENDOR_GEAR):
                        embed = self.render_vendor_gear(item)
                    elif collection == get_collection_name(VENDOR_GEAR_MODS):
                        embed = self.render_vendor_gear_mod(item)
                    elif collection == get_collection_name(VENDOR_WEAPON_MODS):
                        embed = self.render_vendor_weapon_mod(item)
            
            if embed != None:
                event.msg.reply(embed=embed)
        else:
            event.msg.reply('<http://rubenalamina.mx/the-division-weekly-vendor-reset/>')
    
    def render_status_command(self):
        param = {
            "orderBy": "time desc",
            "recordsPerPage": 1,
            "page": 0
        }

        res = requests.get(BACKEND_HOST + '/document/vendors-update', params=param, headers={SESSION_HEADER: self.session}).json()
        info = res['data'][0]
        
        today = arrow.utcnow()
        reset_text = ""

        if today.weekday() == 5:
            reset_text = "in 6 days"
        else:
            temp = today.shift(weekday=5)
            reset_text = temp.humanize()
        
        last_updated = arrow.Arrow.fromtimestamp(info['time'])

        embed = MessageEmbed()
        embed.title = "Last Updated %s" % last_updated.humanize()
        embed.description = "by %s" % info['updater']
        
        embed.add_field(name='Next Vendor Reset (in game)', value=reset_text, inline=True)

        return embed

    def reply_item_not_found(self, query, event):
        pieces = ["vest", "backpack", "mask", "gloves", "knee pads", "holster"]
        temp = [i for i in pieces if (" " + i) in query]

        if len(temp) > 0:
            gear_piece = query.strip(" " + temp[0])
            if gear_piece in self.names:
                event.msg.reply('Sorry, no gearset or highend item like that this week')
            else:
                event.msg.reply('Are you sure %s exists?' % query)
        elif query in ["performance mod", "stamina mod", "electronics mod", "weapon mod"]:
            event.msg.reply('Sorry, no mod like that this week')

        elif util.aliases or query in self.names or query in self.vendor_names:
            event.msg.reply("Sorry, no item like that this week")

        else:
            event.msg.reply("Are you sure this item exists?")


    def handle_update(self, event):
        if not self.lock.locked():
            start_time = time.time()
            self.lock.acquire()

            event.msg.reply("Vendors update initiated by Master @%s" % (str(event.author)))
            vendors.update()

            # log the update in the db
            info = {
                "updater": str(event.author),
                "time": int(time.time()),
                "server": event.guild.name,
                "server_id": event.guild.id
            }

            requests.post(BACKEND_HOST + "/document/vendors-update", json=info, headers={SESSION_HEADER: self.session})

            # release lock
            self.lock.release()

            duration = time.time() - start_time
            event.msg.reply("Update done. Duration: `{0:.2f}s`".format(duration))
        else:
            event.msg.reply("update is already running")


    def render_multiple_items(self, items):
        embed = MessageEmbed()
        embed.description = "found in %s items" % len(items)
        embed.color = 0xDA9513

        for item in items:
            collection = item["@class"]

            if collection == get_collection_name(VENDOR_WEAPONS):
                talents = " **-** ".join([ i for i in [item['talent1'], item['talent2'], item['talent3']] if i.strip() != "-"])
                body = '''`%s`  |  **%s** DMG  |  %s''' % (item["vendor"], item['dmg'], talents.strip())

                embed.add_field(name=item["name"], value=body)
            elif collection == get_collection_name(VENDOR_GEAR):
                major_attrs = item["major"].strip().strip("-").split("<br/>")
                minor_attrs = item["minor"].strip().strip("-").split("<br/>")

                main_stats = []
                if (item['fire'].strip().strip('-')):
                    main_stats.append("**Firearms:** %s" % item['fire'])
                if (item['stam'].strip().strip('-')):
                    main_stats.append("**Stamina:** %s" % item['stam'])
                if (item['elec'].strip().strip('-')):
                    main_stats.append("**Electronics:** %s" % item['elec'])

                all_attrs = "  **|**  ".join(main_stats + [i for i in major_attrs + minor_attrs if i != ""])
                
                body = "`%s`  |  %s" % (item["vendor"], all_attrs)

                embed.add_field(name=item["name"], value=body)
            elif collection == get_collection_name(VENDOR_GEAR_MODS):
                attr = item["attribute"]

                body = "`%s` | %s | %s" % (item["vendor"], item['stat'], attr)
                embed.add_field(name=item['name'], value=body)
            elif collection == get_collection_name(VENDOR_WEAPON_MODS):
                attrs = item['attributes'].split("<br/>")

                attrs_str = " **|** ".join([i for i in attrs[:3]])

                body = "`%s` | %s " % (item["vendor"], attrs_str)
                embed.add_field(name=item["name"], value=body)
            else: return None
        
        return embed

    def render_vendor_weapon(self, weapon):
        embed = MessageEmbed()

        embed.title = weapon['name']
        embed.description = weapon['vendor']
        # embed.add_field(name='Vendor', value=weapon['vendor'], inline=True)
        embed.add_field(name='Price', value=weapon['price'], inline=True)
        embed.add_field(name="Damage", value=weapon['dmg'], inline=True)
        embed.add_field(name='Bonus', value=weapon['bonus'], inline=True)
        
        talents = " **-** ".join([ i for i in [weapon['talent1'], weapon['talent2'], weapon['talent3']] if i.strip() != "-"])
        embed.add_field(name='Talents', value=talents)
        
        if weapon['type'] == 'exotic':
            embed.color = 0xCF5A2E
        else:
            embed.color = 0xDA9513

        return embed
    
    def render_vendor_gear_mod(self, gearmod):
        embed = MessageEmbed()

        embed.title = gearmod['name']
        embed.description = gearmod['vendor']

        embed.add_field(name='Price', value=gearmod['price'], inline=True)
        embed.add_field(name='Stat', value=gearmod['stat'], inline=True)
        embed.add_field(name='Attribute', value=gearmod['attribute'])

        if gearmod['type'] == 'purple-mod':
            embed.color = 0x993D78
        else:
            embed.color = 0xDA9513
        
        return embed
    
    def render_vendor_weapon_mod(self, weaponmod):
        embed = MessageEmbed()

        embed.title = weaponmod['name']
        embed.description = weaponmod['vendor']

        embed.add_field(name='Price', value=weaponmod['price'], inline=True)
        # embed.add_field(name='Stat', value=weaponmod[''], inline=True)
        attr = " **-** ".join(weaponmod["attributes"].split('<br/>'))
        embed.add_field(name='Attribute', value=attr)
        embed.color = 0xDA9513

        return embed

    def render_vendor_gear(self, gear):
        embed = MessageEmbed()

        embed.title = gear['name']
        embed.description = gear['vendor']

        embed.add_field(name='Price', value=gear['price'], inline=True)
        embed.add_field(name='Armor', value=gear['armor'], inline=True)
        embed.add_field(name="Gearscore", value=gear['score'], inline=True)

        if (gear['fire'].strip().strip('-')):
            embed.add_field(name='Firearms', value=gear['fire'], inline=True)
        if (gear['stam'].strip().strip('-')):
            embed.add_field(name='Stamina', value=gear['stam'], inline=True)
        if (gear['elec'].strip().strip('-')):
            embed.add_field(name='Electronics', value=gear['elec'], inline=True)
        
        major_attr = "  **|**  ".join(gear["major"].strip().strip("-").split("<br/>"))
        minor_attr = "  **|**  ".join(gear["minor"].strip().strip("-").split("<br/>"))

        if major_attr:
            embed.add_field(name='Major Attribute(s)', value=major_attr, inline=True)
        
        if minor_attr:
            embed.add_field(name='Minor Attribute(s)', value=minor_attr, inline=True)
        
        if gear['rarity'] == 'header-he':
            embed.color = 0xDA9513
        else:
            embed.color = 0x07C973
        
        return embed
    
    def render_weapon_talent(self, talent):
        embed = MessageEmbed()
        # embed.set_author(name='GearSheet')

        embed.title = talent['name']
        embed.description = talent['description']

        req = talent['requirements']['34']
        req_str = '**electronics**: %s, **firearms**: %s, **stamina**: %s' % \
                  ('none' if req['electronics'] == 0 else req['electronics'],
                   'none' if req['firearms'] == 0 else req['firearms'],
                   'none' if req['stamina'] == 0 else req['stamina'])

        embed.add_field(name='Rolls On', value=', '.join(talent['rollsOn']), inline=True)
        embed.add_field(name='Requirements', value=req_str, inline=True)

        if 'note' in talent.keys():
            embed.set_footer(text=talent['note'])

        embed.color = 0xDA9513

        return embed

    def render_player_talent(self, talent):
        embed = MessageEmbed()

        embed.title = talent['name']
        embed.description = talent['description']

        embed.add_field(name='Type', value=talent['type'], inline=True)
        embed.add_field(name='Benefits', value=talent['benefit'], inline=True)

        embed.color = 0xDA9513

        return embed

    def render_gear_talent(self, talent):
        embed = MessageEmbed()

        embed.title = talent['name']
        embed.description = talent['description']

        embed.set_footer(text='Rolls on %s' % talent['slot'])

        embed.color = 0xDA9513

        return embed

    def render_gearset(self, gearset):
        embed = MessageEmbed()

        embed.title = gearset['name']

        embed.add_field(name='2 piece bonus', value=gearset['2'], inline=True)
        embed.add_field(name='3 piece bonus', value=gearset['3'], inline=True)
        embed.add_field(name='4 piece bonus', value=gearset['4'])
        embed.add_field(name='5 piece bonus', value=gearset['5'], color='489979')
        embed.add_field(name='6 piece bonus', value=gearset['6'])

        embed.set_footer(text="added in patch %s" % gearset['patch'])
        embed.color = '52377'

        return embed

    def render_weapon(self, weapon):
        self.normalize(weapon)
        embed = MessageEmbed()

        embed.title = weapon['name']

        embed.add_field(name='Type', value=weapon['type'], inline=True)
        embed.add_field(name='Variant', value=weapon['variant'], inline=True)
        embed.add_field(name='RPM', value=weapon['rpm'], inline=True)

        embed.add_field(name='Scaling', value=weapon['scaling'], inline=True)
        embed.add_field(name='Magazine Size', value=weapon['MagSize'], inline=True)
        embed.add_field(name='Optimal Range(m)', value=weapon['OptimalRange'], inline=True)

        embed.add_field(name='Reload Speed(ms)', value=weapon['ReloadSpeed'], inline=True)
        embed.add_field(name='Headshot Multiplier', value=weapon['HeadshotMultiplier'], inline=True)
        embed.add_field(name='Native Bonus', value=weapon['WeaponBonus'], inline=True)

        embed.add_field(name='Bonus', value=weapon['Bonus'], inline=True)

        damageStr = "%s - %s" % (weapon['256']['min'], weapon['256']['max'])

        embed.add_field(name='Base Damage', value=damageStr, inline=True)

        if 'modCompat' in weapon.keys():
            compat = ', '.join(weapon['modCompat']['compat'])
            embed.add_field(name='Compatible Mods', value=compat)

            if 'note' in weapon['modCompat'].keys():
                embed.set_footer(text="%s" % weapon['modCompat']['note'])

        if 'talent' in weapon.keys():
            description = weapon['talent']['description']
            embed.description = description

        embed.color = 0xDA9513


        return embed

    def normalize(self, item):  # don't give empty params to bot embed
        for i in item.keys():
            if type(item[i]) is str and len(item[i]) == 0:
                item[i] = '-'

    def render_weapon_mods(self, mod):
        embed = MessageEmbed()
        key_names = {"Mod_Category", "name", "Primary_Attribute", "Mod_Type", "Crit_Chance",
                     "Crit_Damage", "Headshot_Damage", "Accuracy", "Stability", "Reload_Speed",
                    "Rate_Of_Fire", "Optimal_Range", "Magazine_Size", "Decreased_Threat", "Increased_Threat"}

        for key in mod.keys():
            if key == 'name':
                embed.title = mod['name']
            elif key in key_names:
                val_str = ", ".join(mod[key]) if type(mod[key]) is list else mod[key]
                embed.add_field(name=key.replace("_", " "), value=val_str, inline=True)

        embed.set_footer(text="All mods will roll their Primary Attributes, "
                              "as well as an additional 2 attributes")

        embed.color = 0xDA9513

        return embed

    def render_exotic_gear(self, exotic_gear):
        embed = MessageEmbed()

        embed.title = exotic_gear['name']
        embed.description = exotic_gear['description']

        embed.color = 0xCF5A2E
        return embed

    def render_gear_attribute(self, gear_attribute):
        embed = MessageEmbed()

        key_names = ["type", "name", "Minimum_Total", "Mask", "Body_Armor", "Backpack", "Gloves", "Knee_Pads", "Holster",
                     "Maximum_Total", "Max_With_Gear_Mods"]

        for key in gear_attribute.keys():
            if key == 'name':
                embed.title = gear_attribute[key]
            elif key in key_names:
                val = gear_attribute[key]
                embed.add_field(name=key.replace("_", " "), value=val, inline=True)
        
        embed.color = 0xDA9513

        return embed
Example #5
0
class Lock(object):
    """ UNIX-specific exclusive file locks (released when the process ends).

    Based on
    http://blog.vmfarms.com/2011/03/cross-process-locking-and.html,
    adapted for context managers (the 'with' statement).

    Modified to be gevent-safe! Locks held by a given Greenlet may not be
    taken by other Greenlets until released, _as long as you only create one
    Lock object per lockfile_. THIS IS VERY IMPORTANT. *Make sure* that you're
    not creating multiple locks on the same file from the same process,
    otherwise you'll bypass the gevent lock!

    Parameters
    ----------
    f : file or str
        File handle or filename to use as the lock.
    block : bool
        Whether to block or throw IOError if the lock is grabbed multiple
        times.
    """

    TIMEOUT = 60

    def __init__(self, f, block=True):
        if isinstance(f, io.IOBase):
            self.filename = f.name
            self.handle = f if not f.closed else open(f, "w")  # noqa: SIM115
        else:
            self.filename = f
            mkdirp(os.path.dirname(f))
            self.handle = open(f, "w")  # noqa: SIM115
        if block:
            self.lock_op = fcntl.LOCK_EX
        else:
            self.lock_op = fcntl.LOCK_EX | fcntl.LOCK_NB
        self.block = block
        self.gevent_lock = BoundedSemaphore(1)

    def acquire(self):
        got_gevent_lock = self.gevent_lock.acquire(blocking=self.block)
        if not got_gevent_lock:
            raise IOError(
                "cannot acquire gevent lock; associated file is {}".format(
                    self.filename))
        fcntl.flock(self.handle, self.lock_op)

    def release(self):
        fcntl.flock(self.handle, fcntl.LOCK_UN)
        self.gevent_lock.release()

    def locked(self):
        return self.gevent_lock.locked()

    def __enter__(self):
        self.acquire()
        return self

    def __exit__(self, type, value, traceback):
        self.release()

    def __del__(self):
        self.handle.close()