Ejemplo n.º 1
0
    def __init__(self,
                 util,
                 listeners,
                 rows,
                 columns,
                 voice_assistant,
                 d=None,
                 turn_page=None,
                 page_in_title=True,
                 show_loading=False):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        :param rows: menu rows
        :param d: dictionary with menu button flags
        :param turn_page: turn page callback
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        self.player = None
        self.turn_page = turn_page
        self.page_in_title = page_in_title
        self.show_loading = show_loading

        self.cache = Cache(self.util)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "menu_screen_screen_title", True, self.layout.TOP)

        color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT]
        self.menu_layout = self.layout.CENTER

        if d:
            self.menu_button_layout = self.get_menu_button_layout(d)
            self.img_rect = self.menu_button_layout.image_rectangle

        listeners[GO_LEFT_PAGE] = self.previous_page
        listeners[GO_RIGHT_PAGE] = self.next_page

        try:
            self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners,
                                           color_dark_light, d[4])
            Container.add_component(self, None)
            Container.add_component(self, self.navigator)
        except:
            Container.add_component(self, None)

        self.total_pages = 0
        self.current_page = 1
        self.menu = None
Ejemplo n.º 2
0
    def get(self, user_id, page_id):

        ratelimit_key = self.ratelimit_key_template % self.request.remote_ip
        remote_ip_rate = Cache.incr(ratelimit_key)
        if remote_ip_rate is None:
            Cache.set(ratelimit_key, 1, time=60)
        elif remote_ip_rate > 60:
            self.set_status(503)
            self.set_header('Retry-After', '60')
            self.write(
                'Rate limit exceeded. Please do not make more than 60 requests per minute.'
            )

            # Don't log every single time we rate limit a host (that would get spammy fast),
            # but do log significant breakpoints on exactly how spammy a host is being.
            if remote_ip_rate in (61, 100, 1000, 10000):
                logging.info('Rate limited IP %s - %s requests/min' %
                             (self.request.remote_ip, remote_ip_rate))

            return self.finish()

        self.gplus_user_id = user_id
        self.gplus_page_id = page_id

        if len(user_id) != 21:
            self.write(
                "Google+ profile IDs are exactly 21 digits long. Please specify a proper profile ID."
            )
            return self.finish()

        if page_id and len(page_id) != 21:
            self.write(
                "Google+ page IDs are exactly 21 digits long. Please specify a proper page ID."
            )

        self.cache_key = self.cache_key_template % user_id
        if page_id:
            self.cache_key += str(page_id)

        cached_result = Cache.get(self.cache_key)
        flush_requested = self.request.arguments.get('flush', [None])[0]
        if cached_result:
            if not Config.getboolean('cache',
                                     'allow-flush') or not flush_requested:
                return self._respond(**cached_result)

        if page_id:
            OAuth2Handler.authed_fetch(
                user_id, self.json_url % (page_id, self.request.remote_ip),
                self._on_api_response)
        else:
            OAuth2Handler.authed_fetch(
                user_id, self.json_url % ('me', self.request.remote_ip),
                self._on_api_response)
Ejemplo n.º 3
0
		def wrap_callback(response):
			if response.code == 401:
				Cache.delete(cls.auth_cache_key_template % user_id)

				# Retry once to see if we can use a refresh token to get a new key.
				if _authed_fetch_retry:
					cls.authed_fetch(user_id, url, callback, _authed_fetch_retry=False, *args, **kwargs)
				else:
					logging.warning("Abandoning request for %s after retry.", url)
			else:
				return callback(response)
Ejemplo n.º 4
0
	def on_profile_request_complete(self, person):
		"""Callback for the initial OAuth flow's call to fetch_person_by_token."""
		# We compute the time= param here to take into account potential time
		# spent during the API call.
		Cache.set(self.auth_cache_key_template  % person['id'], self.gplus_access_token,
			time=int((self.gplus_expires_at - datetime.datetime.today()).total_seconds()),
		)

		# store refresh token and gplus user id in database
		if self.gplus_refresh_token is not None:
			TokenIdMapping.update_refresh_token(person['id'], self.gplus_refresh_token)
	
		self.set_cookie('gplus_id', str(person['id']))
		self.redirect('/')
Ejemplo n.º 5
0
def main():
    """
    更新
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', default="config.json")
    get_config(path=parser.parse_args().c)

    if get_config('dns', 'dnspod').startswith('ali'):
        dns = alidns
    elif get_config('dns', 'dnspod').startswith('dnscom'):
        dns = dnscom
    else:
        dns = dnspod
    dns.ID, dns.TOKEN = get_config('id'), get_config('token')
    dns.PROXY = get_config('proxy')
    ip.DEBUG = get_config('debug')

    cache = get_config('cache', True) and Cache(CACHE_FILE)
    if cache is False:
        print("Cache is disabled!")
    elif len(cache) < 1 or get_config.time >= cache.time:
        cache.clear()
        print("=" * 25, time.ctime(), "=" * 25, sep=' ')
    update_ip('4', cache, dns)
    update_ip('6', cache, dns)
Ejemplo n.º 6
0
def main():
    """
    更新
    """
    parser = ArgumentParser(description=__description__,
                            epilog=__doc__, formatter_class=RawTextHelpFormatter)
    parser.add_argument('-v', '--version',
                        action='version', version=__version__)
    parser.add_argument('-c', '--config',
                        default="config.json", help="run with config file [配置文件路径]")
    get_config(path=parser.parse_args().config)
    # Dynamicly import the dns module as configuration
    dns_provider = str(get_config('dns', 'dnspod').lower())
    dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider)
    dns.ID, dns.TOKEN = get_config('id'), get_config('token')
    if get_config('debug'):
        ip.DEBUG = get_config('debug')
        basicConfig(
            level=DEBUG,
            format='%(asctime)s <%(module)s.%(funcName)s> %(lineno)d@%(pathname)s \n[%(levelname)s] %(message)s')
        info("DDNS[%s] run: %s,%s", __version__, os_name, sys.platform)

    proxy = get_config('proxy') or 'DIRECT'
    proxy_list = proxy.strip('; ') .split(';')

    cache = get_config('cache', True) and Cache(CACHE_FILE)
    if cache is False:
        warning("Cache is disabled!")
    elif len(cache) < 1 or get_config.time >= cache.time:
        cache.clear()
        print("=" * 25, ctime(), "=" * 25, sep=' ')
    update_ip('4', cache, dns, proxy_list)
    update_ip('6', cache, dns, proxy_list)
Ejemplo n.º 7
0
def main():
    """
    更新
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', default="config.json")
    get_config(path=parser.parse_args().c)
    # Dynamicly import the dns module as configuration
    dns_provider = str(get_config('dns', 'dnspod').lower())
    dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider)
    dns.ID, dns.TOKEN = get_config('id'), get_config('token')
    if get_config('debug'):
        ip.DEBUG = get_config('debug')
        logging.basicConfig(
            level=logging.DEBUG,
            format=
            '%(asctime)s <%(module)s.%(funcName)s> %(lineno)d@%(pathname)s \n[%(levelname)s] %(message)s'
        )
        logging.info("DDNS[%s] run: %s,%s", __version__, os.name, sys.platform)

    proxy = get_config('proxy') or 'DIRECT'
    proxy_list = proxy.strip('; ').split(';')

    cache = get_config('cache', True) and Cache(CACHE_FILE)
    if cache is False:
        print("Cache is disabled!")
    elif len(cache) < 1 or get_config.time >= cache.time:
        cache.clear()
        print("=" * 25, time.ctime(), "=" * 25, sep=' ')
    update_ip('4', cache, dns, proxy_list)
    update_ip('6', cache, dns, proxy_list)
Ejemplo n.º 8
0
	def access_token_for_id(cls, id, callback):
		"""Returns the access token for an id, acquiring a new one if necessary."""
		token = Cache.get(cls.auth_cache_key_template % id)
		if token:
			return IOLoop.instance().add_callback(lambda: callback(token))

		# If we don't have an access token cached, see if we have a refresh token
		token = TokenIdMapping.lookup_refresh_token(id)
		if token:
			post_body = urllib.urlencode({
				'client_id': Config.get('oauth', 'client-id'),
				'client_secret': Config.get('oauth', 'client-secret'),
				'refresh_token': token,
				'grant_type': 'refresh_token',
			})
			http_client = AsyncHTTPClient()
			return http_client.fetch(
				'https://accounts.google.com/o/oauth2/token',
				lambda response: cls.on_refresh_complete(response, id, callback),
				method='POST',
				body=post_body,
				request_timeout=20.0,
				connect_timeout=15.0,
			)
		else:
			logging.error("Unable to update access token for %s, no refresh token stored.", id)
			return IOLoop.instance().add_callback(lambda: callback(None))
Ejemplo n.º 9
0
Archivo: atom.py Proyecto: astore/pluss
	def _on_api_response(self, response):
		if response is None:
			logging.error("API request for %s failed." % self.gplus_user_id)
			self.write("Unable to fetch content for this Google+ ID; it may not be authenticated. See http://%s for more information." % self.request.host)
			self.set_status(401)
			return self.finish()
		if response.error:
			if response.code == 403:
				logging.error("API Request 403: %r" % (json.loads(response.body)))
				self.set_status(503)
				self.write("Unable to fulfill request at this time - Google+ API rate limit exceeded.")
				return self.finish()
			else:
				logging.error("AsyncHTTPRequest error: %r, %r" % (response.error, response))
				return self.send_error(500)
		else:
			data = json.loads(response.body)

			headers = {'Content-Type': 'application/atom+xml'}
			params = {
				'userid': self.gplus_page_id or self.gplus_user_id,
				'baseurl': 'http://%s' % self.request.host,
				'requesturi': 'http://%s%s' % (self.request.host, self.request.uri.split('?', 1)[0]),
			}

			if 'items' not in data or not data['items']:
				params['lastupdate'] = dateutils.to_atom_format(datetime.datetime.today())
				return self._respond(headers, empty_feed_template.format(**params))

			posts = data['items']

			lastupdate = max(dateutils.from_iso_format(p['updated']) for p in posts)
			params['author'] = xhtml_escape(posts[0]['actor']['displayName'])
			params['lastupdate'] = dateutils.to_atom_format(lastupdate)

			headers['Last-Modified'] = dateutils.to_http_format(lastupdate)

			params['entrycontent'] = u''.join(entry_template.format(**get_post_params(p)) for p in posts)

			body = feed_template.format(**params)

			Cache.set(self.cache_key, {'headers': headers, 'body': body}, time=Config.getint('cache', 'stream-expire'))
			return self._respond(headers, body)
Ejemplo n.º 10
0
Archivo: atom.py Proyecto: astore/pluss
	def get(self, user_id, page_id):

		ratelimit_key = self.ratelimit_key_template % self.request.remote_ip
		remote_ip_rate = Cache.incr(ratelimit_key)
		if remote_ip_rate is None:
			Cache.set(ratelimit_key, 1, time=60)
		elif remote_ip_rate > 60:
			self.set_status(503)
			self.set_header('Retry-After', '60')
			self.write('Rate limit exceeded. Please do not make more than 60 requests per minute.')

			# Don't log every single time we rate limit a host (that would get spammy fast),
			# but do log significant breakpoints on exactly how spammy a host is being.
			if remote_ip_rate in (61, 100, 1000, 10000):
				logging.info('Rate limited IP %s - %s requests/min' % (self.request.remote_ip, remote_ip_rate))

			return self.finish()

		self.gplus_user_id = user_id
		self.gplus_page_id = page_id

		if len(user_id) != 21:
			self.write("Google+ profile IDs are exactly 21 digits long. Please specify a proper profile ID.")
			return self.finish()

		if page_id and len(page_id) != 21:
			self.write("Google+ page IDs are exactly 21 digits long. Please specify a proper page ID.")

		self.cache_key = self.cache_key_template % user_id
		if page_id:
			self.cache_key += str(page_id)

		cached_result = Cache.get(self.cache_key)
		flush_requested = self.request.arguments.get('flush', [None])[0]
		if cached_result:
			if not Config.getboolean('cache', 'allow-flush') or not flush_requested:
				return self._respond(**cached_result)

		if page_id:
			OAuth2Handler.authed_fetch(user_id, self.json_url % (page_id, self.request.remote_ip), self._on_api_response)
		else:
			OAuth2Handler.authed_fetch(user_id, self.json_url % ('me', self.request.remote_ip), self._on_api_response)
Ejemplo n.º 11
0
 def __init__(self, listeners, util, site_parser, voice_assistant):
     """ Initializer
     
     :param listeners: screen listeners
     :param util: utility object 
     :param site_parser: site parser        
     """
     FilePlayerScreen.__init__(self, listeners, util, self.get_playlist,
                               voice_assistant)
     self.config = util.config
     self.current_playlist = None
     self.parser = site_parser
     self.cache = Cache(self.util)
     self.current_book_state = None
     self.current_track_index = 0
     self.playlist = self.get_playlist()
     self.audio_files = self.get_audio_files_from_playlist()
     self.loading_listeners = []
     self.reset_loading_listeners = []
     self.LOADING = util.config[LABELS][KEY_LOADING]
Ejemplo n.º 12
0
	def on_refresh_complete(cls, response, id, callback):
		"""Callback for request to get a new access token based on refresh token."""

		if response.code in (400, 401):

			if 'invalid_grant' in response.body:
				# Our refresh token is invalid, which means that we don't have
				# permission to access this user's content anymore. Forget them.
				Cache.delete(cls.auth_cache_key_template % id)
				Cache.delete(cls.profile_cache_key_template % id)
				TokenIdMapping.remove_id(id)
				logging.error("Access was revoked for %s; cached data deleted.", id)

			logging.error("HTTP %s while trying to refresh access token for %s.", response.code, id)
			return IOLoop.instance().add_callback(lambda: callback(None))

		elif response.code != 200:
			logging.error("Non-200 response to refresh token request (%s, id=%s): %r" % (response.code, id, response.body))
			return IOLoop.instance().add_callback(lambda: callback(None))

		results = json.loads(response.body)

		# sanity check
		if results['token_type'] != "Bearer":
			logging.error('Unknown token type received: %s' % results['token_type'])
			return IOLoop.instance().add_callback(lambda: callback(None))

		token = results['access_token']
		Cache.set(cls.auth_cache_key_template % id, token, time=results['expires_in'])

		IOLoop.instance().add_callback(lambda: callback(token))
Ejemplo n.º 13
0
	def fetch_person_by_id(cls, id, callback):
		"""Returns a dict representing a Person, given their G+ id."""

		# If we have them cached already, just return that.
		person = Cache.get(cls.profile_cache_key_template % id)
		if person:
			return person
		
		# If we don't have the person cached, but we do have an
		# access token, use that to fetch the person.
		cls.access_token_for_id(id,
			lambda token: cls.fetch_person_by_token(token, callback),
		)
Ejemplo n.º 14
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.config = config
        self.bot_config = self.config['bot']
        self.session = aiohttp.ClientSession()
        self.logger = logger
        self.cache = Cache()
        self.database = Database(self.config['database'])
        self.pool = None
        self.debug = debug
        self.title = self.bot_config['title']

        self.base_extensions = self.bot_config['extensions']['base']
        self.debug_extensions = self.bot_config['extensions']['debug']

        if self.debug:
            self.bot_extensions = self.base_extensions + self.debug_extensions
            self.token = self.bot_config['debug_token']
            self.prefix = self.bot_config['debug_prefix']
        else:
            self.bot_extensions = self.base_extensions
            self.token = self.bot_config['production_token']
            self.prefix = self.bot_config['production_prefix']
def main():
    """
    更新
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', default="config.json")
    get_config(path=parser.parse_args().c)
    # Dynamicly import the dns module as configuration
    dns_provider = str(get_config('dns', 'dnspod').lower())
    dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider)
    dns.ID, dns.TOKEN = get_config('id'), get_config('token')
    dns.DOMAIN = get_config('domain')

    ip.DEBUG = get_config('debug')

    proxy = get_config('proxy') or 'DIRECT'
    proxy_list = proxy.strip('; ') .split(';')


    print ("=" * 26, "=" * len(time.ctime()), "=" * 26, "\n", sep='')

    print(" " * 30, "%s" % (dns.DOMAIN.encode("utf8")).rjust( len(time.ctime())/2 - 2),"\n",sep="")

    print ("=" * 25, time.ctime(), "=" * 25, "\n", sep=' ')


    cache = get_config('cache', True) and Cache(CACHE_FILE)

    print("[OGetting]  [Address]")

    # address = get_ip("4")
    print("[Now]".rjust(10) + "  [" +  get_ip("4") + "]")
    cache = False;

    if cache is False:
        # print("Cache is disabled!")
        print ("[Cache]".rjust(10),"[Disabled]",sep="  ")
    elif len(cache) < 1 or get_config.time >= cache.time:
        cache.clear()
        # print ("=" * 25, time.ctime(), "=" * 25, sep=' ')
        print ("[Cache]".rjust(10),"[Cleared]",sep="  ")

    update_ip('4', cache, dns, proxy_list)
    # update_ip('6', cache, dns, proxy_list)
    print('[Session]'.rjust(10)+"  [End]", end=" ")
    print("\n")
    print ("_" * 25, time.ctime(), "_" * 25, sep=' ')
    print ("_" * 26, "_" * len(time.ctime()), "_" * 26, "\n", sep='')

    print("\n")
Ejemplo n.º 16
0
Archivo: run.py Proyecto: xcxnig/DDNS
def main():
    """
    更新
    """
    init_config(__description__, __doc__, __version__)
    # Dynamicly import the dns module as configuration
    dns_provider = str(get_config('dns', 'dnspod').lower())
    dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider)
    dns.Config.ID = get_config('id')
    dns.Config.TOKEN = get_config('token')
    dns.Config.TTL = get_config('ttl')
    if get_config('debug'):
        ip.DEBUG = get_config('debug')
        basicConfig(
            level=DEBUG,
            format=
            '%(asctime)s <%(module)s.%(funcName)s> %(lineno)d@%(pathname)s \n[%(levelname)s] %(message)s'
        )
        print("DDNS[", __version__, "] run:", os_name, sys.platform)
        if get_config("config"):
            print("Configuration was loaded from <==",
                  path.abspath(get_config("config")))
        print("=" * 25, ctime(), "=" * 25, sep=' ')

    proxy = get_config('proxy') or 'DIRECT'
    proxy_list = proxy if isinstance(
        proxy, list) else proxy.strip('; ').replace(',', ';').split(';')

    cache = get_config('cache', True) and Cache(CACHE_FILE)
    if cache is False:
        info("Cache is disabled!")
    elif get_config("config_modified_time") is None or get_config(
            "config_modified_time") >= cache.time:
        warning("Cache file is out of dated.")
        cache.clear()
    elif not cache:
        debug("Cache is empty.")
    update_ip('4', cache, dns, proxy_list)
    update_ip('6', cache, dns, proxy_list)
Ejemplo n.º 17
0
    def __init__(self):
        handlers = [
            (r'/', IndexHandler),  # 首页
            # (r'/wx', WxHandler),  # 微信授权页面
            (r'/pay/wx', PayHandler),  # 支付
            # (r'/pay_test', PayWeixinTestHandler),  # 微信支付测试页
            (r'/api/address', address.AddressHandler),
            (r'/api/recom_item', recom_item.DetailHandler),
            (r'/api/home', home.HomeHandler),
            (r'/api/itemlist', home.ItemHandler),
            (r'/api/auth/login', auth.LoginHandler),
            (r'/api/order', order.OrderHandler),
            (r'/api/util/smscode', util.SmscodeHandler),
            (r'/api/util/region', util.RegionHandler),

            # (r'/download/yc', YcDownloadHandler),  # 有菜下载
            (r'/coupon', CouponHandler),  # 有菜优惠券
            (r'/api/coupon', coupon.CouponHandler),  # 有菜获取优惠券接口
            (r'/api/update_mobile', coupon.UpdateMobileHandler),  # 更改红包领取手机号
            (r'/coupon/info', CouponInfoHandler),  # 有菜优惠券说明
        ]
        settings = dict(
            debug=options.debug,
            xsrf_cookies=True,
            login_url='/login',
            cookie_secret='alA9P3tIUGFe3boFVM2A2tmusiRsrTGdgm8Vrk=',
            static_path=os.path.join(ROOT_PATH, 'static') if options.debug else
            os.path.join(os.path.dirname(ROOT_PATH), 'static'),
            template_path=os.path.join(ROOT_PATH, 'templates'),
            db={
                'hamlet': motor.MotorClient(MONGO_HAMLET['master']).hamlet,
                'store': motor.MotorClient(MONGO_STORE['master']).store,
                'youcai': motor.MotorClient(MONGO_YOUCAI['master']).youcai
            },
            cache=Cache(CACHE_SERVER),
            session_manager=SessionManager(SESSION_SECRET, SESSION_SERVER,
                                           SESSION_TIMEOUT, not options.debug))
        super(YoucaiWeb, self).__init__(handlers, **settings)
Ejemplo n.º 18
0
def main():
    """
    更新
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', default="config.json")
    get_config(path=parser.parse_args().c)
    # Dynamicly import the dns module as configuration
    dns_provider = str(get_config('dns', 'dnspod').lower())
    dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider)
    dns.ID, dns.TOKEN = get_config('id'), get_config('token')
    dns.PROXY = get_config('proxy')

    ip.DEBUG = get_config('debug')

    cache = get_config('cache', True) and Cache(CACHE_FILE)
    if cache is False:
        print("Cache is disabled!")
    elif len(cache) < 1 or get_config.time >= cache.time:
        cache.clear()
        print ("=" * 25, time.ctime(), "=" * 25, sep=' ')
    update_ip('4', cache, dns)
    update_ip('6', cache, dns)
Ejemplo n.º 19
0
	def on_fetch_person_complete(cls, response, callback):
		"""Callback for the people/me API call in fetch_person_by_token."""
		person = json.loads(response.body)
		Cache.set(cls.profile_cache_key_template % person['id'], person, time=Config.getint('cache', 'profile-expire'))
		return IOLoop.instance().add_callback(lambda: callback(person))
Ejemplo n.º 20
0
import openpyxl

from const import (
    HttpStatus, )
from config import (
    QIANBIDAO_USER,
    QIANBIDAO_PASSWORD,
    RECEIPTS,
)
from util.http import HttpClient
from util.mail import mail_multipart
from util.cache import Cache
from util.decorators import singleton, retry

cache = Cache(default_values={'qianbidao': {'last_id': '55c433b917a672bd'}})


class QianBiDaoCrawler(object):

    QianBiDaoAppHeaders = {
        'User-Agent': 'PencilNews/1.3.0 (iPhone; iOS 11.2.5; Scale/2.00)',
        'Accept-Encoding': 'br, gzip, deflate',
        'Accept-Language': 'zh-Hans-CN;q=1, en-CN;q=0.9',
        'Authority': 'api.pencilnews.cn',
    }
    login_url = 'https://api.pencilnews.cn/user/login'

    def __init__(self, username, password):
        self.httpclient = HttpClient(default_headers=self.QianBiDaoAppHeaders)
        self.username = username
Ejemplo n.º 21
0
class MenuScreen(Screen):
    """ Site Menu Screen. Base class for all book menu screens """
    def __init__(self,
                 util,
                 listeners,
                 rows,
                 columns,
                 voice_assistant,
                 d=None,
                 turn_page=None,
                 page_in_title=True):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        :param rows: menu rows
        :param d: dictionary with menu button flags
        :param turn_page: turn page callback
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.factory = Factory(util)
        self.bounding_box = self.config[SCREEN_RECT]
        self.player = None
        self.turn_page = turn_page
        self.page_in_title = page_in_title

        self.cache = Cache(self.util)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "menu_screen_screen_title", True, self.layout.TOP)

        color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT]
        self.menu_layout = self.layout.CENTER

        self.menu_button_layout = self.get_menu_button_layout(d)
        self.img_rect = self.menu_button_layout.image_rectangle

        listeners[GO_LEFT_PAGE] = self.previous_page
        listeners[GO_RIGHT_PAGE] = self.next_page

        try:
            self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners,
                                           color_dark_light, d[4])
            Container.add_component(self, None)
            Container.add_component(self, self.navigator)
        except:
            Container.add_component(self, None)

        self.total_pages = 0
        self.current_page = 1
        self.menu = None

        self.loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]

    def get_menu_button_layout(self, d):
        """ Return menu button layout
        
        :param d: dictionary with menu button flags
        
        :return: menu button layout
        """
        s = State()
        s.show_img = True
        s.show_label = True
        button_w = int(self.menu_layout.w / d[1])
        button_h = int(self.menu_layout.h / d[0])
        label_padding = 2
        image_padding = 4
        try:
            self.show_author = d[2]
        except:
            self.show_author = False

        try:
            self.show_genre = d[3]
        except:
            self.show_genre = False

        s.bounding_box = Rect(0, 0, button_w, button_h)
        return MultiLineButtonLayout(s, label_padding, image_padding)

    def previous_page(self, state):
        """ Handle click on left button 
        
        :param state: button state object
        """
        if self.current_page == 1:
            return

        self.current_page -= 1
        if getattr(state, "select_last", False):
            self.components[1].selected_index = 0

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0
        self.turn_page()

    def next_page(self, state):
        """ Handle click on right button 
        
        :param state: button state object
        """
        if self.total_pages <= 1 or self.total_pages == self.current_page:
            return

        self.current_page += 1

        if self.current_page > self.total_pages:
            self.current_page = self.total_pages

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0
        self.turn_page()

    def set_menu(self, menu):
        """ Set menu 
        
        :param menu: menu object
        """
        self.menu = self.components[1] = menu

    def set_title(self, page_num):
        """ Set screen title 
        
        :param page_num: menu page number
        """
        if self.total_pages == 1 or not self.page_in_title:
            self.screen_title.set_text(self.title)
            return

        if len(str(page_num)) <= len(str(self.total_pages)):
            self.screen_title.set_text(self.title + " (" + str(page_num) + ")")

    def reset_title(self):
        """ Reset screen title """

        self.screen_title.set_text(self.title + " (" + str(self.current_page) +
                                   ")")

    def go_to_page(self, page_num):
        """ Handle go to page event 
        
        :param page_num: menu page number
        """
        n = int(page_num)
        if n > self.total_pages:
            n = self.total_pages
        if n == 0:
            n = 1
        self.current_page = n
        self.menu.current_page = self.current_page
        self.turn_page()

    def get_image_from_cache(self, url):
        """ Return image from cache
        
        :param url: image url
        
        :return: image
        """
        return self.cache.get_image(url)

    def put_image_to_cache(self, url, img):
        """ Put image into cache
        
        :param url: image url
        :param img: image
        """
        self.cache.cache_image(img, url)

    def set_button_image(self, b, icon, img_y=None):
        """ Set button image
        
        :param b: button
        :param icon: image
        :param img_y: image Y coordinate
        """
        bb = b.bounding_box
        comps = b.components
        im = comps[1]
        im.content = icon
        w = im.content.get_size()[0]
        h = im.content.get_size()[1]
        im.content_x = bb.x + (bb.width - w) / 2

        if img_y == None:
            img_area_height = bb.height - ((bb.height / LINES) * 2)
            img_y = bb.y + (img_area_height - h) / 2

        im.content_y = img_y
        self.components[1].clean_draw_update()

    def set_loading(self, name):
        """ Show Loading... sign
        
        :name: screen title
        """
        b = self.config[COLORS][COLOR_DARK]
        f = self.config[COLORS][COLOR_BRIGHT]
        fs = int(self.bounding_box.h * 0.07)
        bb = self.menu_layout
        t = self.factory.create_output_text(self.LOADING, bb, b, f, fs)
        t.set_text(self.LOADING)
        self.screen_title.set_text(name)
        self.set_visible(True)
        self.add_component(t)
        self.clean_draw_update()
        self.notify_loading_listeners()

    def reset_loading(self):
        """ Remove Loading... sign """

        del self.components[-1]
        self.notify_loading_listeners()

    def add_loading_listener(self, listener):
        """ Add loading listener
        
        :param listener: event listener
        """
        if listener not in self.loading_listeners:
            self.loading_listeners.append(listener)

    def notify_loading_listeners(self):
        """ Notify all loading listeners """

        for listener in self.loading_listeners:
            listener(None)
Ejemplo n.º 22
0
    def _on_api_response(self, response):
        if response is None:
            logging.error("API request for %s failed." % self.gplus_user_id)
            self.write(
                "Unable to fetch content for this Google+ ID; it may not be authenticated. See http://%s for more information."
                % self.request.host)
            self.set_status(401)
            return self.finish()
        if response.error:
            if response.code == 403:
                logging.error("API Request 403: %r" %
                              (json.loads(response.body)))
                self.set_status(503)
                self.write(
                    "Unable to fulfill request at this time - Google+ API rate limit exceeded."
                )
                return self.finish()
            else:
                logging.error("AsyncHTTPRequest error: %r, %r" %
                              (response.error, response))
                return self.send_error(500)
        else:
            data = json.loads(response.body)

            headers = {'Content-Type': 'application/atom+xml'}
            params = {
                'userid':
                self.gplus_page_id or self.gplus_user_id,
                'baseurl':
                'http://%s' % self.request.host,
                'requesturi':
                'http://%s%s' %
                (self.request.host, self.request.uri.split('?', 1)[0]),
            }

            if 'items' not in data or not data['items']:
                params['lastupdate'] = dateutils.to_atom_format(
                    datetime.datetime.today())
                return self._respond(headers,
                                     empty_feed_template.format(**params))

            posts = data['items']

            lastupdate = max(
                dateutils.from_iso_format(p['updated']) for p in posts)
            params['author'] = xhtml_escape(posts[0]['actor']['displayName'])
            params['lastupdate'] = dateutils.to_atom_format(lastupdate)

            headers['Last-Modified'] = dateutils.to_http_format(lastupdate)

            params['entrycontent'] = u''.join(
                entry_template.format(**get_post_params(p)) for p in posts)

            body = feed_template.format(**params)

            Cache.set(self.cache_key, {
                'headers': headers,
                'body': body
            },
                      time=Config.getint('cache', 'stream-expire'))
            return self._respond(headers, body)
Ejemplo n.º 23
0
class MenuScreen(Screen):
    """ Site Menu Screen. Base class for all book menu screens """
    def __init__(self,
                 util,
                 listeners,
                 rows,
                 columns,
                 voice_assistant,
                 d=None,
                 turn_page=None,
                 page_in_title=True,
                 show_loading=False):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        :param rows: menu rows
        :param d: dictionary with menu button flags
        :param turn_page: turn page callback
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        self.player = None
        self.turn_page = turn_page
        self.page_in_title = page_in_title
        self.show_loading = show_loading

        self.cache = Cache(self.util)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "menu_screen_screen_title", True, self.layout.TOP)
        self.menu_layout = self.layout.CENTER

        if d:
            self.menu_button_layout = self.get_menu_button_layout(d)
            self.img_rect = self.menu_button_layout.image_rectangle

        listeners[GO_LEFT_PAGE] = self.previous_page
        listeners[GO_RIGHT_PAGE] = self.next_page

        self.total_pages = 0
        self.current_page = 1
        self.menu = None

    def get_menu_button_layout(self, d):
        """ Return menu button layout
        
        :param d: dictionary with menu button flags
        
        :return: menu button layout
        """
        s = State()
        s.show_img = True
        s.show_label = True
        button_w = int(self.menu_layout.w / d[1])
        button_h = int(self.menu_layout.h / d[0])
        label_padding = 2
        image_padding = 4
        try:
            self.show_author = d[2]
        except:
            self.show_author = False

        try:
            self.show_genre = d[3]
        except:
            self.show_genre = False

        s.bounding_box = Rect(0, 0, button_w, button_h)
        return MultiLineButtonLayout(s, label_padding, image_padding)

    def previous_page(self, state):
        """ Handle click on left button 
        
        :param state: button state object
        """
        if self.current_page == 1:
            return

        self.current_page -= 1
        if getattr(state, "select_last", False):
            self.components[1].selected_index = 0

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0

        if self.show_loading:
            self.set_loading(self.screen_title.text)

        self.turn_page()

        if self.show_loading:
            self.reset_loading()

    def next_page(self, state):
        """ Handle click on right button 
        
        :param state: button state object
        """
        if self.total_pages <= 1 or self.total_pages == self.current_page:
            return

        self.current_page += 1

        if self.current_page > self.total_pages:
            self.current_page = self.total_pages

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0

        if self.show_loading:
            self.set_loading(self.screen_title.text)

        self.turn_page()

        if self.show_loading:
            self.reset_loading()

    def set_menu(self, menu):
        """ Set menu 
        
        :param menu: menu object
        """
        self.menu = menu
        self.add_component(self.menu)

    def set_title(self, page_num):
        """ Set screen title 
        
        :param page_num: menu page number
        """
        if self.total_pages == 1 or not self.page_in_title:
            self.screen_title.set_text(self.title)
            return

        if len(str(page_num)) <= len(str(self.total_pages)):
            self.screen_title.set_text(self.title + " (" + str(page_num) + ")")

    def reset_title(self):
        """ Reset screen title """

        self.screen_title.set_text(self.title + " (" + str(self.current_page) +
                                   ")")

    def go_to_page(self, page_num):
        """ Handle go to page event 
        
        :param page_num: menu page number
        """
        n = int(page_num)
        if n > self.total_pages:
            n = self.total_pages
        if n == 0:
            n = 1
        self.current_page = n
        self.menu.current_page = self.current_page
        self.turn_page()

    def get_image_from_cache(self, url):
        """ Return image from cache
        
        :param url: image url
        
        :return: image
        """
        return self.cache.get_image(url)

    def put_image_to_cache(self, url, img):
        """ Put image into cache
        
        :param url: image url
        :param img: image
        """
        self.cache.cache_image(img, url)

    def set_button_image(self, b, icon, img_y=None):
        """ Set button image
        
        :param b: button
        :param icon: image
        :param img_y: image Y coordinate
        """
        bb = b.bounding_box
        comps = b.components
        im = comps[1]
        im.content = icon
        w = im.content.get_size()[0]
        h = im.content.get_size()[1]
        im.content_x = bb.x + (bb.width - w) / 2

        if img_y == None:
            img_area_height = bb.height - ((bb.height / LINES) * 2)
            img_y = bb.y + (img_area_height - h) / 2

        im.content_y = img_y
        self.components[1].clean_draw_update()

    def set_loading(self, name, text=None):
        """ Show Loading... sign
        
        :param name: screen title
        :param text: screen text
        """
        Screen.set_loading(self, name, self.menu_layout, text)
Ejemplo n.º 24
0
class BookPlayer(FilePlayerScreen):
    """ Book Player Screen """
    def __init__(self, listeners, util, site_parser, voice_assistant):
        """ Initializer
        
        :param listeners: screen listeners
        :param util: utility object 
        :param site_parser: site parser        
        """
        FilePlayerScreen.__init__(self, listeners, util, self.get_playlist,
                                  voice_assistant)
        self.config = util.config
        self.image_util = util.image_util

        self.current_playlist = None
        self.parser = site_parser
        self.cache = Cache(self.util)
        self.current_book_state = None
        self.current_track_index = 0
        self.playlist = self.get_playlist()
        self.audio_files = self.get_audio_files_from_playlist()
        self.loading_listeners = []
        self.reset_loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]

    def get_playlist(self):
        """ Return current playlist
        
        :return: playlist
        """
        return self.current_playlist

    def set_book(self, new_track, state=None):
        """ Set book
        
        :param new_track: flag defining if track is new
        :param state: button state object 
        """
        self.set_loading()

        self.current_book_state = state
        img_url = None
        if hasattr(state, "event_origin"):
            img_url = state.event_origin.state.icon_base[0]
        elif hasattr(state, "img_url"):
            img_url = state.img_url
        self.current_playlist = self.parser.get_book_audio_files_by_url(
            state.book_url, img_url)
        state.url = self.parser.book_parser.img_url

        img = self.cache.get_image(state.url)
        if img == None:
            i = self.image_util.load_image_from_url(state.url)
            if i:
                self.cache.cache_image(i[1], state.url)
                img = i[1]

        bb = self.file_button.bounding_box
        w = bb.w
        h = bb.h
        self.cover_image = self.image_util.scale_image_with_padding(w,
                                                                    h,
                                                                    img,
                                                                    padding=1)

        self.screen_title.set_text(state.name)

        if self.current_playlist == None:
            return

        self.playlist = self.current_playlist

        if new_track and self.playlist:
            self.config[AUDIOBOOKS][BROWSER_BOOK_TITLE] = state.name
            self.config[AUDIOBOOKS][BROWSER_BOOK_URL] = state.book_url
            self.config[AUDIOBOOKS][BROWSER_IMAGE_URL] = img_url
            self.config[AUDIOBOOKS][BROWSER_TRACK_FILENAME] = self.playlist[0][
                "title"]
            state.track_time = self.config[AUDIOBOOKS][BROWSER_BOOK_TIME] = "0"
        elif not new_track:
            state.track_time = self.config[AUDIOBOOKS][BROWSER_BOOK_TIME]

        self.audio_files = self.playlist

    def set_current(self, new_track=False, state=None):
        """ Set current file 
        
        :param new_track: True - new audio file
        :param state: button state object 
        """
        if state.source == BOOK_MENU or state.source == INIT:
            if self.current_book_state and self.current_book_state.book_url == state.book_url and self.time_control.timer_started:
                return

            self.current_track_index = 0
            if state.source == INIT:
                new_track = False
            else:
                new_track = True
            self.set_book(new_track, state)
        elif state.source == TRACK_MENU:
            if getattr(state, "index",
                       None) and state.index == self.current_track_index:
                return
            new_track = True
            st = {"file_name": state.file_name}
            self.set_current_track_index(st)
        elif state.source == ARROW_BUTTON:
            new_track = True
            st = {"file_name": state.file_name}
            self.set_current_track_index(st)
        elif state.source == RESUME:
            new_track = False
            st = {"file_name": state.file_name}
            self.set_current_track_index(st)
        elif state.source == HOME_NAVIGATOR or state.source == BOOK_NAVIGATOR_BACK or state.source == BOOK_NAVIGATOR or state.source == GO_PLAYER:
            return

        if getattr(state, "url", None):
            self.file_button.components[
                1].image_filename = self.img_filename = state.url
        else:
            if hasattr(self, "img_filename"):
                self.file_button.components[
                    1].image_filename = self.img_filename
            else:
                self.file_button.components[
                    1].image_filename = self.img_filename = None
        img = self.cover_image
        if img:
            self.file_button.components[1].content = img
            self.file_button.state.icon_base = img
            self.file_button.state.show_bgr = True
            self.file_button.state.bgr = self.config[COLORS][COLOR_MEDIUM]
            self.file_button.add_background(self.file_button.state)
            self.file_button.components[
                1].content_x = self.layout.CENTER.x + int(
                    (self.layout.CENTER.w - img.get_size()[0]) / 2)
            if self.layout.CENTER.h > img.get_size()[1]:
                self.file_button.components[
                    1].content_y = self.layout.CENTER.y + int(
                        (self.layout.CENTER.h - img.get_size()[1]) / 2)
            else:
                self.file_button.components[1].content_y = self.layout.CENTER.y

        if self.current_playlist == None:
            return

        self.set_audio_file(new_track, state)

    def set_audio_file(self, new_track, s=None):
        """ Set new audio file
        
        :param new_track: True - new audio file
        :param s: button state object 
        """
        state = State()
        state.playback_mode = FILE_AUDIO
        state.playlist_track_number = 0
        name = url = None

        if s == None:
            if self.config[AUDIOBOOKS][BROWSER_TRACK_FILENAME]:
                name = self.config[AUDIOBOOKS][BROWSER_TRACK_FILENAME]
                for t in self.playlist:
                    if t["title"].endswith(name):
                        url = t["mp3"]
            else:
                i = 0
                if s != None:
                    i = s.index
                t = self.playlist[i]
                url = t["mp3"]
                name = t["title"]
        else:
            if getattr(s, "track_filename", None):
                i = self.get_current_track_index(
                    {"file_name": s.track_filename})
            elif getattr(s, "playlist_track_number", None):
                i = s.playlist_track_number
            else:
                i = self.current_track_index

            t = self.playlist[i]
            url = t["mp3"]
            name = t["title"]

        self.config[PLAYER_SETTINGS][PAUSE] = False
        state.file_name = name
        self.config[AUDIOBOOKS][BROWSER_TRACK_FILENAME] = t["file_name"]
        state.mute = self.config[PLAYER_SETTINGS][MUTE]
        state.pause = self.config[PLAYER_SETTINGS][PAUSE]
        self.play_button.draw_default_state(None)

        if self.config[VOLUME_CONTROL][
                VOLUME_CONTROL_TYPE] == VOLUME_CONTROL_TYPE_PLAYER:
            state.volume = self.config[PLAYER_SETTINGS][VOLUME]
        else:
            state.volume = None

        state.file_type = FILE_AUDIO
        state.dont_notify = True
        state.source = FILE_AUDIO
        state.url = url
        state.mode = AUDIOBOOKS

        state.playback_mode = FILE_AUDIO
        state.music_folder = self.config[AUDIO][MUSIC_FOLDER]
        self.audio_files = self.get_audio_files_from_playlist()

        if self.config[AUDIOBOOKS][BROWSER_BOOK_TIME]:
            if new_track:
                state.track_time = "0"
            else:
                state.track_time = self.config[AUDIOBOOKS][BROWSER_BOOK_TIME]

        self.reset_loading()

        logging.debug(state.url)

        self.notify_play_listeners(state)

    def get_audio_files(self):
        """ Return audio files from playlist
        
        :return: files
        """
        return self.get_audio_files_from_playlist()

    def get_audio_files_from_playlist(self):
        """ Call player for files in the playlist 
        
        :return: list of files from playlist
        """
        files = []
        if getattr(self, "playlist", None):
            for n in range(len(self.playlist)):
                st = State()
                st.index = st.comparator_item = n
                t = self.playlist[n]
                st.file_type = FILE_AUDIO
                st.file_name = t["file_name"]
                files.append(st)
        return files

    def set_loading(self):
        """ Show Loading... sign """

        b = self.config[COLORS][COLOR_DARK]
        f = self.config[COLORS][COLOR_BRIGHT]
        fs = 20
        bx = self.file_button.bounding_box
        x = bx.x - 1
        y = bx.y
        w = bx.w + 2
        h = bx.h
        bb = pygame.Rect(x, y, w, h)
        t = self.factory.create_output_text(self.LOADING, bb, b, f, fs)
        t.set_text(self.LOADING)
        t.layer_name = self.LOADING
        self.left_button.change_label("")
        self.right_button.change_label("")
        self.add_component(t)
        self.clean_draw_update()
        self.notify_loading_listeners()

    def reset_loading(self):
        """ Remove Loading... sign """

        n = getattr(self.components[-1], "layer_name", None)
        if n and n == self.LOADING:
            del self.components[-1]
            pygame.event.clear()
        self.notify_reset_loading_listeners()

    def add_loading_listener(self, listener):
        """ Add loading listener
        
        :param listener: event listener
        """
        if listener not in self.loading_listeners:
            self.loading_listeners.append(listener)

    def notify_loading_listeners(self):
        """ Notify all loading listeners """

        for listener in self.loading_listeners:
            listener(None)

    def add_reset_loading_listener(self, listener):
        """ Add reset loading listener
        
        :param listener: event listener
        """
        if listener not in self.reset_loading_listeners:
            self.reset_loading_listeners.append(listener)

    def notify_reset_loading_listeners(self):
        """ Notify all reset loading listeners """

        for listener in self.reset_loading_listeners:
            listener(None)

    def add_screen_observers(self, update_observer, redraw_observer,
                             start_time_control, stop_time_control,
                             title_to_json):
        """ Add screen observers
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        :param start_time_control:
        :param stop_time_control:
        :param title_to_json:
        """
        FilePlayerScreen.add_screen_observers(self, update_observer,
                                              redraw_observer,
                                              start_time_control,
                                              stop_time_control, title_to_json)
        self.add_loading_listener(redraw_observer)
        self.add_reset_loading_listener(redraw_observer)
Ejemplo n.º 25
0
class FFF(commands.AutoShardedBot):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.config = config
        self.bot_config = self.config['bot']
        self.session = aiohttp.ClientSession()
        self.logger = logger
        self.cache = Cache()
        self.database = Database(self.config['database'])
        self.pool = None
        self.debug = debug
        self.title = self.bot_config['title']

        self.base_extensions = self.bot_config['extensions']['base']
        self.debug_extensions = self.bot_config['extensions']['debug']

        if self.debug:
            self.bot_extensions = self.base_extensions + self.debug_extensions
            self.token = self.bot_config['debug_token']
            self.prefix = self.bot_config['debug_prefix']
        else:
            self.bot_extensions = self.base_extensions
            self.token = self.bot_config['production_token']
            self.prefix = self.bot_config['production_prefix']

    async def on_ready(self):
        # self.remove_command("help")
        self.pool = await self.database.connect()
        await self.update_cache()
        await self.load_extensions()
        await self.update_activity()

        self.logger.info(f"Logged in as {self.user} ({self.user.id}).")
        if self.debug:
            self.logger.critical(
                "Starting in debug mode, do not use this in production!")

    async def close(self):
        self.logger.info("\nShutting down!")
        await super(FFF, self).close()
        await self.session.close()
        await self.pool.close()

    async def on_message_edit(self, before, after):
        if after.author.bot:
            return
        await self.process_commands(after)

    async def on_command_error(self, ctx, error):
        if isinstance(error, commands.CommandNotFound):
            pass
        elif isinstance(error, commands.CheckFailure):
            pass
        elif isinstance(error, commands.MissingRequiredArgument):
            await ctx.send("Invalid command arguments!")
        else:
            try:
                raise error
            except Exception as error:
                cause = str(error.__cause__)
                owner = self.get_user(self.owner_ids[0])
                length = 1024 - (len(cause) + 3)

                embed = Embed(title="An error has occurred!",
                              color=ctx.author.color)
                embed.add_field(name=cause,
                                value=str(traceback.format_exc()[:length]) +
                                "...",
                                inline=False)
                embed.add_field(name="Command name",
                                value=ctx.command.qualified_name,
                                inline=False)
                embed.add_field(name="Executed by",
                                value=f"`{ctx.author}` ({ctx.author.id})",
                                inline=False)
                embed.add_field(
                    name="Executed in",
                    value=f"`{ctx.guild.name}` ({ctx.guild.id})\n"
                    f"<#{ctx.channel.id}> (`{ctx.channel.name}`, {ctx.channel.id})",
                    inline=False)
                await owner.send(embed=embed)

                embed = Embed(title="An error has occurred!",
                              color=ctx.author.color)
                embed.add_field(
                    name=cause,
                    value="The owner has been notified about this error.")
                await ctx.send(embed=embed)
                self.logger.error(traceback.format_exc())

    async def load_extensions(self):
        for extension in self.bot_extensions:
            self.load_extension(f"extensions.{extension}")
            self.logger.info(f"Loaded {extension}.")
        self.logger.info("Starting...")

    async def update_activity(self):
        activity = discord.Activity(
            name=self.config['bot']['activity']['name'],
            type=getattr(discord.ActivityType,
                         self.config['bot']['activity']['type']))
        await self.change_presence(activity=activity)

    async def update_cache(self):
        self.logger.debug("Updating cache...")
        async with self.pool.acquire() as conn:
            guild_data = await self.database.get_guild_data(conn)
            guild_data_history = await self.database.get_guild_data_history(
                conn)
            self.cache.set({
                "guild_data": guild_data,
                "guild_data_history": guild_data_history
            })
        self.logger.debug("Successfully updated the cache!")