def run(self, m): input = get_input(m, ignore_reply=False) if not input: return self.bot.send_message( m, self.bot.trans.errors.missing_parameter, extra={'format': 'HTML'}) delay = first_word(input) if delay: delaytime = delay[:-1] unit = delay[-1:] if not is_int(delaytime) or is_int(unit): return self.bot.send_message( m, self.bot.trans.plugins.reminders.strings.wrongdelay) alarm = time() + self.to_seconds(delaytime, unit) text = all_but_first_word(input) if not text: return self.bot.send_message( m, self.bot.trans.plugins.reminders.strings.noreminder) reminder = DictObject(OrderedDict()) reminder.id = '%s:%s' % (m.sender.id, time()) reminder.alarm = alarm reminder.chat_id = m.conversation.id reminder.text = text reminder.first_name = m.sender.first_name reminder.username = m.sender.username if not 'list' in self.bot.reminders or not self.bot.reminders.list: self.bot.reminders.list = [] self.bot.reminders.list.append(reminder) self.sort_reminders() if unit == 's': delay = delay.replace('s', ' seconds') if unit == 'm': delay = delay.replace('m', ' minutes') if unit == 'h': delay = delay.replace('h', ' hours') if unit == 'd': delay = delay.replace('d', ' days') message = self.bot.trans.plugins.reminders.strings.added % ( m.sender.first_name, delay, text) return self.bot.send_message(m, message, extra={'format': 'HTML'})
def send_request(url, params=None, headers=None, files=None, data=None, post=False, parse=True, verify=True): try: if post: r = requests.post(url, params=params, headers=headers, files=files, data=data, timeout=100, verify=verify) else: r = requests.get(url, params=params, headers=headers, files=files, data=data, timeout=100, verify=verify) except: logging.error('Error making request to: %s' % url) if verify: return send_request(url, params, headers, files, data, post, parse, False) else: return None if r.status_code != 200: logging.error(r.text) while r.status_code == 429: sleep(5) return send_request(url, params, headers, files, data, post, parse) # r = r.get(url, params=params, headers=headers, # files=files, data=data) try: if parse: return DictObject(json.loads(r.text)) else: return r.url except Exception as e: catch_exception(e) return None
def send_request(url, params=None, headers=None, files=None, data=None, post=False, parse=True, get_text=False): try: if post: r = requests.post(url, params=params, headers=headers, files=files, data=data, timeout=100) else: r = requests.get(url, params=params, headers=headers, files=files, data=data, timeout=100) except: logging.error('Error making request to: %s' % url) return None if r.status_code != 200: logging.error(r.text) while r.status_code == 429: r = r.get(url, params=params, headers=headers, files=files, data=data) try: if parse: return DictObject(json.loads(r.text)) elif get_text: return r.text else: return r.url except: return None
def AXDbg(val, msg, debug=True, kw={}): return AX(val, msg, debug=debug, Utils=DictObject(globals()), kw=kw)
def run(self, m): input = get_input(m) if input: for plugin in self.bot.plugins: text = plugin.description for command in plugin.commands: command = DictObject(command) # If the command is hidden, ignore it # if ('hidden' in command and not command.hidden) or not 'hidden' in command: # Adds the command and parameters# if input in command.command.replace('/', '').rstrip('\s'): text += '\n • ' + command.command.replace( '/', self.bot.config.prefix) if 'parameters' in command and command.parameters: for parameter in command.parameters: name, required = list(parameter.items())[0] # Bold for required parameters, and italic for optional # if required: text += ' <b><%s></b>' % name else: text += ' [%s]' % name if 'description' in command: text += '\n <i>%s</i>' % command.description else: text += '\n <i>?¿</i>' return self.bot.send_message( m, text, extra={'format': 'HTML'}) return self.bot.send_message(m, self.bot.trans.errors.no_results, extra={'format': 'HTML'}) if is_command(self, 3, m.content): text = '' else: text = self.bot.trans.plugins.help.strings.commands # Iterates the initialized plugins # for plugin in self.bot.plugins: for command in plugin.commands: command = DictObject(command) # If the command is hidden, ignore it # if not 'hidden' in command or not command.hidden: # Adds the command and parameters# if is_command(self, 3, m.content): show = False if 'parameters' in command and command.parameters: allOptional = True for parameter in command.parameters: name, required = list(parameter.items())[0] if required: allOptional = False show = allOptional else: show = True if show: text += '\n' + command.command.lstrip('/') if 'description' in command: text += ' - %s' % command.description else: text += ' - ?¿' else: text += '\n • ' + command.command.replace( '/', self.bot.config.prefix) if 'parameters' in command and command.parameters: for parameter in command.parameters: name, required = list(parameter.items())[0] # Bold for required parameters, and italic for optional # if required: text += ' <b><%s></b>' % name else: text += ' [%s]' % name if 'description' in command: text += '\n <i>%s</i>' % command.description else: text += '\n <i>?¿</i>' self.bot.send_message(m, text, extra={'format': 'HTML'})
def get_updates(self, offset=None, limit=100, poll_timeout=0, allowed_updates=None, request_timeout=None, delta=timedelta(milliseconds=100), error_as_empty=False): """ Use this method to receive incoming updates using long polling. An Array of Update objects is returned. You can choose to set `error_as_empty` to `True` or `False`. If `error_as_empty` is set to `True`, it will log that exception as warning, and fake an empty result, intended for use in for loops. In case of such error (and only in such case) it contains an "exception" field. Ìt will look like this: `{"result": [], "exception": e}` This is useful if you want to use a for loop, but ignore Network related burps. If `error_as_empty` is set to `False` however, all `requests.RequestException` exceptions are normally raised. :keyword offset: (Optional) Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as :func:`get_updates` is called with an offset higher than its `update_id`. :type offset: int :param limit: Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100 :type limit: int :param poll_timeout: Timeout in seconds for long polling, e.g. how long we want to wait maximum. Defaults to 0, i.e. usual short polling. :type poll_timeout: int :param allowed_updates: List the types of updates you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used. Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: list of str :param request_timeout: Timeout of the request. Not the long polling server side timeout. If not specified, it is set to `poll_timeout`+2. :type request_timeout: int :param delta: Wait minimal 'delta' seconds, between requests. Useful in a loop. :type delta: datetime. :param error_as_empty: If errors which subclasses `requests.RequestException` will be logged but not raised. Instead the returned DictObject will contain an "exception" field containing the exception occured, the "result" field will be an empty list `[]`. Defaults to `False`. :type error_as_empty: bool Returns: :return: An Array of Update objects is returned, or an empty array if there was an requests.RequestException and error_as_empty is set to True. :rtype: list of pytgbot.api_types.receivable.updates.Update """ assert(offset is None or isinstance(offset, int)) assert(limit is None or isinstance(limit, int)) assert(poll_timeout is None or isinstance(poll_timeout, int)) assert(allowed_updates is None or isinstance(allowed_updates, list)) if poll_timeout and not request_timeout is None: request_timeout = poll_timeout + 2 # end if if delta.total_seconds() > poll_timeout: now = datetime.now() if now - self._last_update < delta: wait = ((now - self._last_update) - delta).total_seconds() # can be 0.2 wait = 0 if wait < 0 else wait if wait != 0: logger.debug("Sleeping {i} seconds.".format(i=wait)) # end if sleep(wait) # end if # end if self._last_update = datetime.now() use_long_polling = poll_timeout != 0 try: result = self.do( "getUpdates", offset=offset, limit=limit, timeout=poll_timeout, allowed_updates=allowed_updates, use_long_polling=use_long_polling, request_timeout=request_timeout ) if self.return_python_objects: logger.debug("Trying to parse {data}".format(data=repr(result))) from pytgbot.api_types.receivable.updates import Update try: return Update.from_array_list(result, list_level=1) except TgApiParseException: logger.debug("Failed parsing as api_type Update", exc_info=True) # end try # no valid parsing so far raise TgApiParseException("Could not parse result.") # See debug log for details! # end if return_python_objects return result except (requests.RequestException, TgApiException) as e: if error_as_empty: if not isinstance(e, requests.exceptions.Timeout) or not use_long_polling: logger.warn( "Network related error happened in get_updates(), but will be ignored: " + str(e), exc_info=True ) # end if self._last_update = datetime.now() if self.return_python_objects: return [] else: return DictObject(result=[], exception=e) # end if else: raise
def init_if_empty(_dict): if _dict: return DictObject(_dict) else: return {}
def run(self, m): input = get_input(m) commands = [] if is_command(self, 2, m.content): text = '' else: text = self.bot.trans.plugins.help.strings.commands # Iterates the initialized plugins # for plugin in self.bot.plugins: if hasattr(plugin, 'commands'): for command in plugin.commands: command = DictObject(command) # Adds the command and parameters# if is_command(self, 2, m.content): show = False if 'parameters' in command and command.parameters: allOptional = True for parameter in command.parameters: name, required = list(parameter.items())[0] if required: allOptional = False show = allOptional else: show = True if self.bot.config.prefix != '/' and ( not 'keep_default' in command or not command.keep_default): show = False if not command.command.startswith('/'): show = False if show: text += '\n' + command.command.lstrip('/') if 'description' in command: text += ' - {}'.format(command.description) commands.append({ 'command': command.command.lstrip('/'), 'description': command.description }) else: text += ' - No description' commands.append({ 'command': command.command.lstrip('/'), 'description': 'No description' }) else: # If the command is hidden, ignore it # if not 'hidden' in command or not command.hidden: doc = generate_command_help( plugin, command['command'], False) if doc: lines = doc.splitlines() text += '\n • {}'.format(lines[0]) if len(lines) > 1: text += '\n {}'.format(lines[1]) else: text += '\n <i>No description</i>' if is_command(self, 2, m.content): self.bot.send_message(m, 'setMyCommands', 'api', extra={'commands': json.dumps(commands)}) self.bot.send_message(m, text, extra={'format': 'HTML'})
import us from census import Census from DictObject import DictObject from geography.conf import settings census = Census(settings.CENSUS_API_KEY) ############ # COUNTIES counties = census.sf1.get("NAME", geo={"for": "county:*"}) county_lookup = DictObject({}) for county in counties: c = DictObject(county) if c.state not in county_lookup: county_lookup[c.state] = {} county_lookup[c.state][c.county] = c.NAME ############# # TOWNSHIPS townships = [] township_states = ["CT", "MA", "ME", "NH", "RI", "VT"] township_lookup = DictObject({}) for state in township_states: state_codes = us.states.lookup(state) for county_fips, name in county_lookup[state_codes.fips].items(): state_townships = census.sf1.get(
def run(self, m): if str(m.sender.id).startswith('-100'): return if m.conversation.id > 0: return self.bot.send_message(m, self.bot.trans.errors.group_only, extra={'format': 'HTML'}) if has_tag(self.bot, m.conversation.id, 'nopole'): return gid = str(m.conversation.id) uid = m.sender.id now = datetime.now().replace(microsecond=0) date = now.isoformat().split('T')[0] text = None # Pole ranking if is_command(self, 1, m.content): if time_in_range(time(1, 0, 0), time(2, 0, 0), now.time()): type = 1 elif time_in_range(time(12, 0, 0), time(13, 0, 0), now.time()): type = 2 else: type = 0 if gid in self.bot.poles: ranking = DictObject() for day in self.bot.poles[gid]: if type == 0: if 'pole' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].pole)].p += 1 except: ranking[str(self.bot.poles[gid][day].pole)] = { 'p': 1, 's': 0, 'f': 0, 'i': 0 } if 'subpole' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].subpole)].s += 1 except: ranking[str( self.bot.poles[gid][day].subpole)] = { 'p': 0, 's': 1, 'f': 0, 'i': 0 } if 'fail' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].fail)].f += 1 except: ranking[str(self.bot.poles[gid][day].fail)] = { 'p': 0, 's': 0, 'f': 1, 'i': 0 } if 'iron' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].iron)].i += 1 except: ranking[str(self.bot.poles[gid][day].iron)] = { 'p': 0, 's': 0, 'f': 0, 'i': 1 } if type == 1: if 'canaria' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].canaria)].c += 1 except: ranking[str( self.bot.poles[gid][day].canaria)] = { 'c': 1 } if type == 2: if 'andaluza' in self.bot.poles[gid][day]: try: ranking[str( self.bot.poles[gid][day].andaluza)].a += 1 except: ranking[str( self.bot.poles[gid][day].andaluza)] = { 'a': 1 } text = '' if type == 0: text = self.bot.trans.plugins.pole.strings.ranking for uid, values in self.order_by_points(ranking, type): points = str((values.p * 3) + (values.s * 1) + (values.f * 0.5) + (values.i * 0.1)).rstrip('0').rstrip('.') text += '\n ' + self.bot.trans.plugins.pole.strings.ranking_points % ( self.bot.users[uid].first_name, points) poles = '\n\n' + self.bot.trans.plugins.pole.strings.poles poles_empty = True for uid, values in self.order_by_poles(ranking): if values.p: poles_empty = False poles += '\n ' + self.bot.trans.plugins.pole.strings.ranking_poles % ( self.bot.users[uid].first_name, values.p) if not poles_empty: text += poles subpoles = '\n\n' + self.bot.trans.plugins.pole.strings.subpoles subpoles_empty = True for uid, values in self.order_by_subpoles(ranking): if values.s: subpoles_empty = False subpoles += '\n ' + self.bot.trans.plugins.pole.strings.ranking_subpoles % ( self.bot.users[uid].first_name, values.s) if not subpoles_empty: text += subpoles fails = '\n\n' + self.bot.trans.plugins.pole.strings.fails fails_empty = True for uid, values in self.order_by_fails(ranking): if values.f: fails_empty = False fails += '\n ' + self.bot.trans.plugins.pole.strings.ranking_fails % ( self.bot.users[uid].first_name, values.f) if not fails_empty: text += fails irons = '\n\n' + self.bot.trans.plugins.pole.strings.irons irons_empty = True for uid, values in self.order_by_irons(ranking): if values.i: irons_empty = False irons += '\n ' + self.bot.trans.plugins.pole.strings.ranking_irons % ( self.bot.users[uid].first_name, values.i) if not irons_empty: text += irons elif type == 1: poles_canarias = '\n\n' + self.bot.trans.plugins.pole.strings.poles_canarias poles_canarias_empty = True for uid, values in self.order_by_poles_canarias(ranking): if values.c: poles_canarias_empty = False poles_canarias += '\n ' + \ self.bot.trans.plugins.pole.strings.ranking_poles % ( self.bot.users[uid].first_name, values.c) if not poles_canarias_empty: text += poles_canarias elif type == 2: poles_andaluzas = '\n\n' + self.bot.trans.plugins.pole.strings.poles_andaluzas poles_andaluzas_empty = True for uid, values in self.order_by_poles_andaluzas(ranking): if values.a: poles_andaluzas_empty = False poles_andaluzas += '\n ' + \ self.bot.trans.plugins.pole.strings.ranking_poles % ( self.bot.users[uid].first_name, values.a) if not poles_andaluzas_empty: text += poles_andaluzas # Pole elif is_command(self, 2, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'pole': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][date]: self.bot.poles[gid][date].pole = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_pole % user # Subole elif is_command(self, 3, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'subpole': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][date]: uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon % self.bot.users[ uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) elif not 'subpole' in self.bot.poles[gid][date]: self.bot.poles[gid][date].subpole = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_subpole % user # Fail elif is_command(self, 4, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'fail': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][ date] or not 'subpole' in self.bot.poles[gid][date]: uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon % self.bot.users[ uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) elif not 'fail' in self.bot.poles[gid][date]: self.bot.poles[gid][date].fail = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_fail % user # Pole canaria elif is_command(self, 5, m.content): if self.has_pole(gid, uid, date, 1): return if not time_in_range(time(1, 0, 0), time(2, 0, 0), now.time()): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'canaria': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'canaria' in self.bot.poles[gid][date]: self.bot.poles[gid][date].canaria = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_pole_canaria % user # Pole andaluza elif is_command(self, 6, m.content): if self.has_pole(gid, uid, date, 1): return if not time_in_range(time(12, 0, 0), time(13, 0, 0), now.time()): uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon_for_andaluza % self.bot.users[ uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'andaluza': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'andaluza' in self.bot.poles[gid][date]: self.bot.poles[gid][date].andaluza = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_pole_andaluza % user # Hierro elif is_command(self, 7, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({date: {'iron': uid}}) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][ date] or not 'subpole' in self.bot.poles[gid][ date] or not 'fail' in self.bot.poles[gid][date]: uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon % self.bot.users[ uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) elif not 'iron' in self.bot.poles[gid][date]: self.bot.poles[gid][date].iron = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = '' if 'first_name' in self.bot.users[uid]: user += self.bot.users[uid]['first_name'] if 'username' in self.bot.users[uid] and self.bot.users[ uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_iron % user # Pole reset elif is_command(self, 8, m.content): if has_tag(self.bot, m.conversation.id, 'polereset'): if is_trusted(self.bot, m.sender.id, m): delete_data('poles/%s/%s' % (self.bot.name, gid)) self.bot.poles.pop(gid, None) text = self.bot.trans.plugins.pole.strings.polereset_done else: text = self.bot.trans.errors.admin_required else: text = self.bot.trans.plugins.config.strings.disabled if text: self.bot.send_message(m, text, extra={'format': 'HTML'})
class EBaseCls(object): """ 大写开头的属性 is 枚举KEY 小写开头的方法 is 辅助方法 关键三元素K/V/T: cls.KEY = Utils.typeByDict(VAL, TEXT=TEXT); cls.key2Text(KEY) EnumSingletonInstance[Key<k[0].isupper()>] = Val __小写驼峰__ is 实例内置方法 __大写驼峰__ is 类静态内置方法 _大写驼峰 is 类静态方法、且整个Based继承树内共用 枚举KEY和枚举VALUE应当在继承树(__WholeInstance)中都唯一 e.g. @ESingletonCls class ECategory(EBaseCls): class _ValObj(EBaseCls._ValObj, unicode): pass Politics = _ValObj.defVal("001", u'政治') Sports = _ValObj.defVal("006", u'体育') ECategory.Politics == ECategory.Politics.VAL == "001" ECategory.Politics.TEXT == u'政治' ECategory.Politics is ECategory['Politics'] ECategory.Politics is not ECategory.Politics.VAL ECategory.__getDict__() == dict(Politics=ECategory.Politics, Sports=ECategory.Sports) ECategory.__IsinstanceT__(ECategory.Politics) == True ECategory.__IsinstanceT__("001") == False ECategory.__IsinstanceT__(ECategory.Undef) == False """ Undef = Undef @classmethod def __IsinstanceT__(cls, inst): """ Utils.isInstanceT(inst, cls_) == cls_.__IsinstanceT__(inst) """ return isinstance( inst, cls._ValObj) and inst in cls.__SingletonInstance.__getObjs__() __SingletonClsDc = DictObject({'EBaseCls': Undef}) __WholeClsDc = DictObject({'EBaseCls': Undef}) # 类的继承组单例对象 __SingletonInstance = UndefCls('EBaseCls._SingletonInstance()') # 类的单例对象 __WholeInstance = UndefCls('EBaseCls._WholeInstance()') # 类所属继承树基类的单例对象 @classmethod def _SingletonClsDc(cls): AX(cls, '').is_equal_to(EBaseCls) return {'EBaseCls': EBaseCls} and EBaseCls.__SingletonClsDc @classmethod def _WholeClsDc(cls): AX(cls, '').is_equal_to(EBaseCls) return {'EBaseCls': EBaseCls} and EBaseCls.__WholeClsDc @classmethod def _SingletonInstance(cls, val=Undef): if val != Undef: # print(' {}._SingletonInstance({!r})'.format(cls.__name__, val)) AX(val, '').is_instance_of(cls) AX(cls.__SingletonInstance, '').isIn([Undef, val]) cls.__SingletonInstance = val AX(cls.__SingletonInstance, '').is_not_equal_to(Undef) return cls and cls.__SingletonInstance @classmethod def _WholeInstance(cls, val=Undef): if val != Undef: # print(' {}._WholeInstance({!r})'.format(cls.__name__, val)) AX(val, '').is_instance_of(cls) AX(cls.__WholeInstance, '').isIn([Undef, val]) cls.__WholeInstance = val AX(cls.__WholeInstance, '').is_not_equal_to(Undef) return cls and cls.__WholeInstance class _ValObj(object): def __init__(self, VAL): bases = self.__class__.__bases__ note = '{!r}.__bases__'.format(self.__class__) AX(bases, note).is_length(2) AX(bases, note).doGeti(0).is_equal_to(EBaseCls._ValObj) bases[1].__init__(self, VAL) # #调用未绑定的超类构造方法【必须显式调用父类的构造方法】 self.VAL = VAL # VAL用于接口层次 self.TEXT = Undef # TEXT用于UI层次 def __DefAttrs__(self, TEXT, **kw): AX(TEXT, 'TEXT').is_instance_of(basestring) self.TEXT = TEXT for k, v in kw.items(): assert k[:1].isupper() and (k not in ['VAL', 'TEXT']), \ "assert k[0].isupper() and (k not in ['VAL', 'TEXT']), but k={!r}".format(k) setattr(self, k, v) return self @classmethod def defVal(cls, VAL, TEXT=Undef, **kw): return cls(VAL).__DefAttrs__(TEXT, **kw) def __getitem__(self, item): return getattr(self, item) @classmethod def defVal(cls, VAL, TEXT=Undef, **kw): return cls._ValObj(VAL).__DefAttrs__(TEXT, **kw) def __init__(self, **kw): cls = self.__class__ self.__objName__ = '{cls.__module__}.{cls.__name__}'.format(cls=cls) AX(self.__objName__, 'self.__objName__').is_not_in(*EBaseCls._SingletonClsDc().keys()) EBaseCls._SingletonClsDc()[self.__objName__] = cls self.__class__.__SingletonInstance = self @classmethod def __Singleton__(cls, **kw): return cls(**kw) @classmethod def __CreateWholeClsThenSingleton__(cls, name='EQueuesLiked', chkMethod=None): AX(cls, 'cls').is_equal_to(EBaseCls) AX(name, 'name').is_instance_of(basestring) bases = [_v for _k, _v in EBaseCls._SingletonClsDc().items() \ if _k.startswith('{}_'.format(name)) and not re.match(r'_[a-z0-9_]', _k)] wholeCls = EBaseCls and type(name, tuple(bases), {}) AX(name, 'name').is_not_in(*EBaseCls._WholeClsDc().keys()) EBaseCls._WholeClsDc()[name] = wholeCls wholeInstance = wholeCls.__Singleton__(isWholeInstance=True) for base in bases: if chkMethod: getattr(base, chkMethod)() base._WholeInstance(wholeInstance) wholeCls._WholeInstance(wholeInstance) return wholeInstance def __getitem__(self, item): """ inst.KEY === inst[KEY] """ return getattr(self, item) def __iter__(self): return (o for o in self.__getObjs__()) def __getDict__(self): items = { k: (self.__class__._ValObj and self[k]) for k in dir(self) if k[0].isupper() } items.pop('Undef') return items getDict = __getDict__ def __getKeys__(self): return self.__getDict__().keys() getKeys = __getKeys__ def __getObjs__(self): return sorted(self.__getDict__().values()) getObjs = __getObjs__ def getVals(self): return [_i.VAL for _i in self.getObjs()] def getTexts(self): return [_i.TEXT for _i in self.getObjs()] def __doUndef__(self, name): return UndefCls('{}.{}'.format(self.__objName__, name)) def __doDefault__(self, method, srcKey, **kw): if not kw.has_key('__Dft__'): assert False, self.__doUndef__('{}({!r})'.format(method, srcKey)) else: return kw['__Dft__'] def __chkVal__(self, enumVal): AX(enumVal, '%s:enumVal' % self.__objName__).isIn(self.__getObjs__()) def key2Val(self, enumKey, **kw): srcDict = self.__getDict__() if not srcDict.has_key(enumKey): ret = self.__doDefault__('key2Val', enumKey, **kw) else: ret = srcDict[enumKey] return self.__class__._ValObj and ret def val2Obj(self, enumVal, **kw): enumKey = self.val2Key(enumVal, **kw) return self.key2Val(enumKey, **kw) def getValSon(self, val, son='TEXT', **kw): valObj = self.val2Obj(val, **kw) if isinstance(valObj, EBaseCls._ValObj ): # 注意这里要用_EBase._ValObj,确保是valObj形式而不是原始的val形式 return valObj[son] else: return kw['__Dft__'] def getValSons(self, son='TEXT'): return [v[son] for v in self.__getObjs__()] def key2Text(self, enumKey, **kw): val = self.key2Val(enumKey, **kw) return self.getValSon(val, 'TEXT') def val2Text(self, enumVal, **kw): enumKey = self.val2Key(enumVal, **kw) return self.key2Text(enumKey, **kw) def val2Key(self, enumVal, **kw): for k, v in self.__getDict__().items(): if v == enumVal: return k else: return self.__doDefault__('val2Key', enumVal, **kw) def __chkWholeInstance__(self): AX(self, 'self').is_equal_to(self.__class__._WholeInstance()) def __chkSingletonInstance(self): AX(self, 'self').is_equal_to(self.__class__._SingletonClsDc()) AX(self, 'self').is_not_equal_to(self.__class__._WholeInstance()) def __wholeVal2SingletonInstance__(self, enumVal, **kw): cls = self.__class__ self.__chkWholeInstance__() wholeCls = EBaseCls._WholeClsDc()[cls._SingletonInstance().__objName__] for base in wholeCls.__bases__: instance = (EBaseCls and base)._SingletonInstance() if enumVal in instance.__getObjs__(): return instance else: assert False, "cann't find enumVal={!r} in cls={}".format( enumVal, cls.__name__)
# encoding=utf-8 from .Utils import Undef, UndefCls from .assertpyx import AX import re from DictObject import DictObject _ESingletonCls_Stores = DictObject({}) _ESingletonInst_Stores = DictObject({}) def ESingletonCls(cls): __objName__ = '{cls.__module__}.{cls.__name__}'.format(cls=cls) inst = cls.__Singleton__() _ESingletonCls_Stores[__objName__] = cls _ESingletonInst_Stores[__objName__] = inst return inst class EBaseCls(object): """ 大写开头的属性 is 枚举KEY 小写开头的方法 is 辅助方法 关键三元素K/V/T: cls.KEY = Utils.typeByDict(VAL, TEXT=TEXT); cls.key2Text(KEY) EnumSingletonInstance[Key<k[0].isupper()>] = Val __小写驼峰__ is 实例内置方法 __大写驼峰__ is 类静态内置方法 _大写驼峰 is 类静态方法、且整个Based继承树内共用
def run(self, m): if m.conversation.id > 0: return self.bot.send_message(m, self.bot.trans.errors.group_only, extra={'format': 'HTML'}) if has_tag(self.bot, m.conversation.id, 'nopole'): return gid = str(m.conversation.id) uid = m.sender.id date = datetime.now().replace(microsecond=0).isoformat().split('T')[0] # Pole ranking if is_command(self, 1, m.content): if gid in self.bot.poles: ranking = DictObject() for day in self.bot.poles[gid]: if 'pole' in self.bot.poles[gid][day]: try: ranking[str(self.bot.poles[gid][day].pole)].p += 1 except: ranking[str(self.bot.poles[gid][day].pole)] = { 'p': 1, 's': 0, 'f': 0 } if 'subpole' in self.bot.poles[gid][day]: try: ranking[str(self.bot.poles[gid][day].subpole)].s += 1 except: ranking[str(self.bot.poles[gid][day].subpole)] = { 'p': 0, 's': 1, 'f': 0 } if 'fail' in self.bot.poles[gid][day]: try: ranking[str(self.bot.poles[gid][day].fail)].f += 1 except: ranking[str(self.bot.poles[gid][day].fail)] = { 'p': 0, 's': 0, 'f': 1 } text = self.bot.trans.plugins.pole.strings.ranking for uid, values in self.order_by_points(ranking): points = str((values.p * 3) + (values.s * 1) + (values.f * 0.5)).rstrip('0').rstrip('.') text += '\n ' + self.bot.trans.plugins.pole.strings.ranking_points % (self.bot.users[uid].first_name, points) poles = '\n\n' + self.bot.trans.plugins.pole.strings.poles poles_empty = True for uid, values in self.order_by_poles(ranking): if values.p: poles_empty = False poles += '\n ' + self.bot.trans.plugins.pole.strings.ranking_poles % (self.bot.users[uid].first_name, values.p) if not poles_empty: text += poles subpoles = '\n\n' + self.bot.trans.plugins.pole.strings.subpoles subpoles_empty = True for uid, values in self.order_by_subpoles(ranking): if values.s: subpoles_empty = False subpoles += '\n ' + self.bot.trans.plugins.pole.strings.ranking_subpoles % (self.bot.users[uid].first_name, values.s) if not subpoles_empty: text += subpoles fails = '\n\n' + self.bot.trans.plugins.pole.strings.fails fails_empty = True for uid, values in self.order_by_fails(ranking): if values.f: fails_empty = False fails += '\n ' + self.bot.trans.plugins.pole.strings.ranking_fails % (self.bot.users[uid].first_name, values.f) if not fails_empty: text += fails # Pole elif is_command(self, 2, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({ date: { 'pole': uid } }) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][date]: self.bot.poles[gid][date].pole = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = self.bot.users[uid].first_name if 'username' in self.bot.users[uid] and self.bot.users[uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_pole % user # Subole elif is_command(self, 3, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({ date: { 'subpole': uid } }) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][date]: uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon % self.bot.users[uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) elif not 'subpole' in self.bot.poles[gid][date]: self.bot.poles[gid][date].subpole = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = self.bot.users[uid].first_name if 'username' in self.bot.users[uid] and self.bot.users[uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_subpole % user # Fail elif is_command(self, 4, m.content): if self.has_pole(gid, uid, date): return if not gid in self.bot.poles: self.bot.poles[gid] = DictObject({ date: { 'fail': uid } }) else: if not date in self.bot.poles[gid]: self.bot.poles[gid][date] = DictObject() if not 'pole' in self.bot.poles[gid][date] or not 'subpole' in self.bot.poles[gid][date]: uid = str(uid) text = self.bot.trans.plugins.pole.strings.too_soon % self.bot.users[uid].first_name return self.bot.send_message(m, text, extra={'format': 'HTML'}) elif not 'fail' in self.bot.poles[gid][date]: self.bot.poles[gid][date].fail = uid else: return set_data('poles/%s/%s/%s' % (self.bot.name, gid, date), self.bot.poles[gid][date]) uid = str(uid) user = self.bot.users[uid].first_name if 'username' in self.bot.users[uid] and self.bot.users[uid].username: user = '******' + self.bot.users[uid].username text = self.bot.trans.plugins.pole.strings.got_fail % user if text: self.bot.send_message(m, text, extra={'format': 'HTML'})