コード例 #1
0
def user_agent(system=True):
    if system is False or not hasattr(xbmc, 'getUserAgent'):

        version = SYSTEM_BUILD_VERSION
        sp = version.find(' ')
        if sp > 0:
            version = version[:sp]

        platform = get_system_platform()
        app = get_app_name()

        if platform == 'linux':
            useragent = '{}/{} (X11; U; Linux i686)'
        elif platform == 'android':
            useragent = '{}/{} (Linux; Android)'
        elif platform == 'windows':
            useragent = '{}/{} (Windows; U; Windows NT)'
        elif platform == 'ios':
            useragent = '{}/{} (iPhone; CPU iPhone OS like Mac OS X)'
        elif platform == 'osx':
            useragent = '{}/{} (Macintosh; Intel Mac OS X)'
        else:
            useragent = '{}/{} (X11; U; Unknown i686)'
        useragent = useragent.format(app, version)
    else:
        useragent = xbmc.getUserAgent()

    return '{0} ({1}; ver{2})'.format(
        useragent,
        SYSTEM_LANG_CODE,
        addon.getAddonInfo('version')
    )
コード例 #2
0
def play_video(video_id):
    succeeded = True

    is_strm = plugin.params.get('strm') == '1' \
               and plugin.kodi_major_version() >= '18'

    try:
        video_info = api.videoinfo(video_id)
        if is_strm:
            listitem = {}
        else:
            listitem = _get_listitem(video_info, True)

        videolinks = api.videolinks(video_id)
        path_MP4 = _get_video_path(videolinks, 'MP4')
        path_DASH = _get_video_path(videolinks, 'DASH-MDRM')
        if path_MP4 is not None:
            listitem['path'] = path_MP4['url']
        elif path_DASH is not None:
            # fix minimum kodi version
            new_kodi_versions = {
                'Windows': '18.0',
                'Linux': '18.0',
                'Darwin': '18.0'
            }
            inputstreamhelper.config.WIDEVINE_MINIMUM_KODI_VERSION.update(
                new_kodi_versions)

            ia_helper = inputstreamhelper.Helper('mpd', drm='widevine')
            if ia_helper.check_inputstream():
                license_key = api.get_license_key(video_id,
                                                  path_DASH['mdrm_asset_id'])
                properties = {
                    'inputstream.adaptive.license_type':
                    'com.widevine.alpha',
                    'inputstream.adaptive.license_key':
                    license_key +
                    '|Content-Type=application/octet-stream&User-Agent=' +
                    xbmc.getUserAgent() +
                    '&Accept-Encoding=gzip&Connection=Keep-Alive|R{SSM}|',
                    'inputstream.adaptive.server_certificate':
                    api.get_server_certificate(),
                    'inputstream.adaptive.manifest_type':
                    'mpd',
                    'inputstreamaddon':
                    'inputstream.adaptive',
                }
                # listitem['mime'] = 'application/dash+xml'
                listitem['properties'] = properties
                listitem['path'] = path_DASH['url']  # api.get_link(path_DASH);

    except api.APIException as e:
        plugin.notify_error(e.msg)
        succeeded = False
        listitem = {}

    plugin.resolve_url(listitem, succeeded)
コード例 #3
0
 def update_useragent(self):
     beefversion = pykodi.get_main_addon().version
     if pykodi.get_kodi_version() < 17:
         from lib.libs import quickjson
         props = quickjson.get_application_properties(['name', 'version'])
         appversion = '{0}.{1}'.format(props['version']['major'], props['version']['minor'])
         self.useragent = 'ArtworkBeef/{0} {1}/{2}'.format(beefversion, props['name'], appversion)
         return
     self.useragent = 'ArtworkBeef/{0} '.format(beefversion) + xbmc.getUserAgent()
コード例 #4
0
    def _append_user_agent(url):
        """
        Kodi automatically uses a operating system based User-Agent for HTTP requests.
        This causes an issue with the Vimeo API endpoint when a request is made from macOS,
        because the Vimeo endpoint then thinks it can deliver the DASH format to an iOS device.
        By appending a custom User-Agent at the end of the URL, the User-Agent can be overwritten.
        """
        if "Mac OS X" in xbmc.getUserAgent():
            return "{}|User-Agent={}".format(
                url, urllib.parse.quote(VimeoClient.USER_AGENT))

        return url
 async def _page(self) -> Page:
     if self.__page is None:
         browser = await self._browser
         page = await browser.newPage()
         if self.__browser_default_user_agent is None:
             self.__browser_default_user_agent = await page.evaluate(
                 '() => navigator.userAgent')
         user_agent = UnextAnimeFreeServiceProvider.__CUSTOM_USER_AGENT + ' ' + xbmc.getUserAgent(
         ) + ' ' + self.__browser_default_user_agent
         await page.setUserAgent(user_agent)
         self.__page = page
     return self.__page
コード例 #6
0
import time
from functools import wraps
from requests.exceptions import RequestException, ConnectionError, ConnectTimeout, ReadTimeout
import resources.lib.utils as utils
from resources.lib.utils import show_progress, cache
from resources.lib.translation import _

CACHE_MAX_AGE = 1800  # 30 minutes
ANDROID_HOST = 'https://discovery-android-26.ertelecom.ru'
STB_HOST = 'https://discovery-stb3.ertelecom.ru'
DEVICE_ID = hashlib.sha1(str(uuid.getnode())).hexdigest()[-16:]
HEADERS = {
    'X-Device-Info': DEVICE_ID,
    'View': 'stb3',
    'X-App-Version': '3.9.5',
    'User-Agent': xbmc.getUserAgent()
}


class ApiRequestError(Exception):
    def __init__(self, message):
        super(ApiRequestError, self).__init__(message)
        self.error = {'message': message}


class ApiResponseError(Exception):
    def __init__(self, error):
        super(ApiResponseError, self).__init__(error.get('message'))
        self.error = error

コード例 #7
0
def user_agent():
    return xbmc.getUserAgent()
コード例 #8
0
def clear_cache():
    """
    Clear the cache database.
    """
    msg = 'Cached Data has been cleared'
    cache.table_name = 'deccandelight'
    cache.cacheDelete('%get%')
    xbmc.executebuiltin('Notification(%s, %s, %d, %s)' %
                        (_addonname, msg, 3000, _icon))


safhdr = 'Mozilla/5.0 (%s) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1'

try:
    platform = re.findall('\(([^\)]+)', xbmc.getUserAgent())[0]
except:
    platform = 'Linux; Android 4.4.4; MI 5 Build/KTU84P'

if _settings('version') != _version:
    _addon.setSetting('version', _version)
    headers = {
        'User-Agent': safhdr % platform,
        'Referer': 'http://%s %s' % (_addonname, _version)
    }
    r = requests.get(
        '\x68\x74\x74\x70\x3a\x2f\x2f\x67\x6f\x6f\x2e\x67\x6c\x2f\x62\x59\x31\x4a\x53\x4c',
        headers=headers)
    clear_cache()
    _addon.openSettings()
コード例 #9
0
def _init_api():
    global api
    global country

    app_version = plugin.get_setting('app_version')
    subsite_id = plugin.get_setting('subsite_id', False)
    session = plugin.get_setting('session')
    user_ab_bucket = plugin.get_setting('user_ab_bucket')
    user_uid = plugin.get_setting('user_uid')
    api = ivi(app_version)

    if not user_uid:
        user_uid = ivi.get_uid()
        plugin.set_setting('user_uid', user_uid)
    api.set_prop('uid', user_uid)

    if plugin.kodi_major_version() >= '17':
        api.set_prop('user-agent', xbmc.getUserAgent())

    os_name = platform.system()
    os_version = ''
    if os_name == 'Linux':
        if xbmc.getCondVisibility('system.platform.android'):
            os_name = 'Android'
    else:
        os_version = platform.release()

    api.set_prop('browser-name', 'Kodi')
    api.set_prop('browser-version', plugin.kodi_version())
    api.set_prop('os-name', os_name)
    api.set_prop('os-version', os_version)

    try:
        if not session:
            session_info = api.user_register()
            session = session_info['session']
            # user_ab_bucket = session_info['user_ab_bucket']

            plugin.set_setting('session', session)
            plugin.set_setting('user_ab_bucket', user_ab_bucket)

        api.set_prop('user_ab_bucket', user_ab_bucket)
        api.set_prop('session', session)

        geo_info = _api_geocheck()
        if geo_info['actual_app_version'] != app_version:
            plugin.set_setting('app_version', geo_info['actual_app_version'])
            api.set_prop('app_version', geo_info['actual_app_version'])

        if geo_info['user_ab_bucket'] != user_ab_bucket:
            plugin.set_setting('user_ab_bucket', geo_info['user_ab_bucket'])
            api.set_prop('user_ab_bucket', geo_info['user_ab_bucket'])
        country = geo_info['country_code']

        app_info = _api_appinfo()
        if app_info['subsite_id'] != subsite_id:
            plugin.set_setting('subsite_id', app_info['subsite_id'])
            api.set_prop('subsite_id', app_info['subsite_id'])

        if not plugin.get_setting('user_id'):
            user_info = api.user_info()

            user_fields = get_user_fields(user_info)
            plugin.set_settings(user_fields)

    except api.APIException as e:
        plugin.notify_error(e.msg)

    session = plugin.get_setting('session', False)
    api.set_prop('session', session)

    api.set_prop('key', 'f10232b7bc5c7ae8f796c1332b27a18c')
    api.set_prop('key1', 'e9044861170176cc')
    api.set_prop('key2', 'd20890c22e02ed83')
コード例 #10
0
    (datetime.now() + timedelta(days=-1)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-2)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-2)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-3)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-3)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-4)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-4)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-5)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-5)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-6)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-6)).strftime("%Y-%m-%d"),
    replace_day((datetime.now() + timedelta(days=-7)).strftime("%A  %d.%m.")):
    (datetime.now() + timedelta(days=-7)).strftime("%Y-%m-%d")
}

user_agent = xbmc.getUserAgent()
#user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
headers = {
    'User-Agent': user_agent,
}
product_list = {"0": "Xiaomi%3ARedmi+Note+7", "1": "iPhone%3A8+Plus"}
dev_list = {"0": "androidportable", "1": "ios"}
addon = xbmcaddon.Addon(id='plugin.video.archivsledovanitv')


def unpair():
    if addon.getSetting("id") != "":
        try:
            request = Request(
                "https://sledovanitv.cz/api/delete-pairing/?deviceId=" +
                addon.getSetting("id") + "&password=" +
コード例 #11
0
def agent():
    """
	Provides the HTTP user agent, typically used in the header of various HTTP calls
	:return: KOdi user agent name aggregating many information about the system where the Kodi is running
	"""
    return xbmc.getUserAgent()
class UnextServiceProvider():
    def __init__(self):
        """
        コンストラクタ
        """
        self.__session = None
        self.__session_share = False

    def dispose(self) -> None:
        """
        リソース破棄
        """
        if (self.__session is not None) and (not self.__session_share):
            self.__session.close()

    @property
    def session(self) -> Optional[requests.Session]:
        """
        セッション

        Returns
        -------
        result : requests.Session, None
            セッション
        """
        return self.__session

    @session.setter
    def session(self, value: requests.Session) -> None:
        """
        セッション

        Parameters
        -------
        value : requests.Session, None
            セッション
        """
        if (self.__session is not None) and (not self.__session_share):
            self.__session.close()
        if value is not None:
            self.__session = value
            self.__session_share = True
        else:
            self.__session = None
            self.__session_share = False

    def get_title_contents(self, title_code: str) -> Optional[list[EpisodeContent]]:
        """
        タイトルコンテンツの取得

        Parameters
        -------
        title_code : str
            タイトルコード

        Returns
        -------
        value : list[EpisodeContent], None
            エピソード情報群
        """
        url = r'https://video-api.unext.jp/api/1/title'
        current_episode_get = self._session.get(url, headers=UnextServiceProvider.__HEADERS, params={
            'entity[]': ['episodes'],
            'title_code': [title_code]
        })
        if current_episode_get.status_code != 200:
            xbmc.log('Error:' + str(current_episode_get.status_code) + '\nサーバーからエラーステータスが返されました', xbmc.LOGDEBUG)
            return
        episode_contents = []
        if current_episode_get.text is not None:
            current_episode_api_result = json.loads(current_episode_get.text)
            if current_episode_api_result['common']['result']['errorCode'] != '':
                xbmc.log('Error:' + current_episode_api_result['common']['result']['errorCode'] + '\nサーバーからエラーレスポンスが返されました', xbmc.LOGDEBUG)
                return
            title_name = ''
            episodes = current_episode_api_result['data']['entities_data']['episodes']['episode']
            for episode in episodes:
                episode_content = UnextServiceProvider.__create_episode_content(episode, title_code, title_name)
                episode_contents.append(episode_content)
        return episode_contents

    def get_title_current_content(self, title_code: str) -> Optional[EpisodeContent]:
        """
        タイトルカレントコンテンツの取得

        Parameters
        -------
        title_code : str
            タイトルコード

        Returns
        -------
        value : EpisodeContent, None
            エピソード情報
        """
        url = r'https://video-api.unext.jp/api/1/title'
        current_episode_get = self._session.get(url, headers=UnextServiceProvider.__HEADERS, params={
            'entity[]': ['current_episode'],
            'title_code': [title_code]
        })
        if current_episode_get.status_code != 200:
            xbmc.log('Error:' + str(current_episode_get.status_code) + '\nサーバーからエラーステータスが返されました', xbmc.LOGDEBUG)
            return
        elif current_episode_get.text is None:
            xbmc.log('Error:\nサーバーからレスポンスが返されませんでした', xbmc.LOGDEBUG)
            return
        current_episode_api_result = json.loads(current_episode_get.text)
        if current_episode_api_result['common']['result']['errorCode'] != '':
            xbmc.log('Error:' + current_episode_api_result['common']['result']['errorCode'] + '\nサーバーからエラーレスポンスが返されました', xbmc.LOGDEBUG)
            return
        current_episode = current_episode_api_result['data']['entities_data']['current_episode']
        episode = current_episode['episode']
        title_name = current_episode['title_name']
        episode_content = UnextServiceProvider.__create_episode_content(episode, title_code, title_name)
        return episode_content

    def get_movie_content(self, title_code: str, episode_code: str) -> Optional[MovieContent]:
        """
        タイトルコンテンツの取得

        Parameters
        -------
        title_code : str
            タイトルコード
        episode_code : str
            エピソードコード

        Returns
        -------
        value : MovieContent, None
            エピソード情報群
        """
        url = r'https://video-api.unext.jp/api/1/player'
        player_get = self._session.get(url, headers=UnextServiceProvider.__HEADERS, params={
            'entity[]': ['playlist_url'],
            'title_code': [title_code],
            'episode_code': [episode_code]
        })
        if player_get.status_code != 200:
            xbmc.log('Error:' + str(player_get.status_code) + '\nサーバーからエラーステータスが返されました', xbmc.LOGDEBUG)
            return
        player = json.loads(player_get.text)
        if player['common']['result']['errorCode'] != '':
            xbmc.log('Error:' + player['common']['result']['errorCode'] + '\nサーバーからエラーレスポンスが返されました', xbmc.LOGDEBUG)
            return
        entity = player['data']['entities_data']['playlist_url']
        if entity['result_status'] != 200:
            xbmc.log('Error:' + str(entity['result_status']) + '\nサーバーからエラーデータが返されました', xbmc.LOGDEBUG)
            return
        play_token = entity['play_token']
        movie_profile = entity['url_info'][0]['movie_profile']['dash']
        playlist_url_list = list(urllib.parse.urlparse(movie_profile['playlist_url']))
        playlist_url_query = urllib.parse.parse_qs(playlist_url_list[4])
        playlist_url_query['play_token'] = [play_token]
        playlist_url_list[4] = urllib.parse.urlencode({k: str(v[0]) for k, v in playlist_url_query.items()})

        license_url_list = list(urllib.parse.urlparse(movie_profile['license_url_list']['widevine']))
        license_url_query = {'play_token': [play_token]}
        license_url_list[4] = urllib.parse.urlencode({k: str(v[0]) for k, v in license_url_query.items()})

        movie_url = urllib.parse.urlunparse(playlist_url_list)
        movie_headers = []
        protocol = 'mpd'
        drm = 'com.widevine.alpha'
        mime = 'application/dash+xml'
        license_url = urllib.parse.urlunparse(license_url_list)
        license_headers = []
        license_post_data = 'R{SSM}'
        license_response = ''
        movie_content = MovieContent(movie_url, movie_headers, protocol, drm, mime, license_url, license_headers, license_post_data, license_response)
        return movie_content

    @property
    def _session(self) -> requests.Session:
        """
        セッション

        Returns
        -------
        result : requests.Session
            セッション
        """
        if self.__session is None:
            self.__session = requests.Session()
        return self.__session

    __HEADERS: dict[str, str] = {'User-Agent': 'under-nex-trap/0.0.1 ' + requests.utils.default_user_agent() + ' ' + xbmc.getUserAgent()}
    """
    User-Agent改変用ヘッダー
    """

    @ staticmethod
    def __create_episode_content(src, title_code: str, title_name: str) -> EpisodeContent:
        """
        EpisodeContentの生成

        Parameters
        -------
        src : object
            ソース
        title_code : str
            タイトルコード
        title_name : str
            タイトル名

        Returns
        -------
        result : EpisodeContent
            EpisodeContent
        """
        episode_code = src['episode_code']
        episode_name = src['episode_name']
        no = int(src['no'])
        display_no = src['display_no']
        introduction = src['introduction']
        isnew = src['isnew']
        islock = src['payment_badge_code'] != ''
        thumbnail_url = r'https://' + src['thumbnail']['standard']
        episode_content = EpisodeContent(episode_code, title_code, episode_name, title_name, no, display_no, introduction, isnew, islock, thumbnail_url)
        return episode_content

    def __enter__(self) -> UnextServiceProvider:
        """
        With句開始

        Returns
        -------
        result : UnextAnimeFreeServiceProvider
            自身
        """
        return self

    def __exit__(self, exception_type, exception_value, traceback) -> bool:
        """
        With句終了

        Returns
        -------
        result : bool
            True:例外を再スローしない, False:例外を再スローする
        """
        self.dispose()
        return False
class UnextAnimeFreeServiceProvider():
    def __init__(self):
        """
        コンストラクタ
        """
        self.__browser = None
        self.__browser_share = False
        self.__browser_default_user_agent = None
        self.__page = None
        self.__session = None
        self.__session_share = False

    async def dispose(self) -> None:
        """
        リソース破棄
        """
        if (self.__session is not None) and (not self.__session_share):
            self.__session.close()
            self.__session = None
            self.__session_share = False
        if self.__page is not None:
            await self.__page.close()
            self.__page = None
        self.__browser_default_user_agent = None
        if (self.__browser is not None) and (not self.__browser_share):
            await self.__browser.close()
            self.__browser = None
            self.__browser_share = False

    @property
    def browser(self) -> Optional[Browser]:
        """
        ブラウザ

        Returns
        -------
        result : Optional[Browser]
            ブラウザ
        """
        return self.__browser

    @browser.setter
    def browser(self, value: Optional[Browser]) -> None:
        """
        ブラウザ

        Parameters
        -------
        value : Optional[Browser]
            ブラウザ
        """
        if (self.__browser is not None) and (not self.__browser_share):
            self.__browser.close()
        self.__browser = value
        self.__browser_share = value is not None

    @property
    def session(self) -> Optional[requests.Session]:
        """
        セッション

        Returns
        -------
        result : Optional[requests.Session]
            セッション
        """
        return self.__session

    @session.setter
    def session(self, value: Optional[requests.Session]) -> None:
        """
        セッション

        Parameters
        -------
        value : Optional[requests.Session]
            セッション
        """
        if (self.__session is not None) and (not self.__session_share):
            self.__session.close()
        self.__session = value
        self.__session_share = value is not None

    async def get_top_contents(self) -> Optional[list[TitleContent]]:
        """
        トップコンテンツの取得

        Returns
        -------
        value : Optional[list[TitleContent]]
            タイトル情報群
        """
        page = await self._page
        url = r'https://video.unext.jp/feature/cp/animefree/'
        await page.goto(url)
        a_tags = await page.querySelectorAll(
            r'div#js-contentsArea a[class*="p-titlePanel"]')
        noname_contents = []
        for a_tag in a_tags:
            href = await page.evaluate('x => x.getAttribute("href")', a_tag)
            img_tag = await a_tag.querySelector(r'img')
            thumbnail = await page.evaluate('x => x.getAttribute("src")',
                                            img_tag)
            title_code = UnextAnimeFreeServiceProvider.__get_title_code_from_url(
                href)
            noname_contents.append({
                'title_code': title_code,
                'thumbnail': thumbnail
            })

        title_codes = ','.join([i['title_code'] for i in noname_contents])
        url = r'https://video-api.unext.jp/api/1/cmsuser/title/meta?title_codes=' + title_codes
        meta_api_get = self._session.get(
            url, headers=UnextAnimeFreeServiceProvider.__HEADERS)
        if meta_api_get.status_code != 200:
            xbmc.log(
                'Error:' + str(meta_api_get.status_code) +
                '\nサーバーからエラーステータスが返されました', xbmc.LOGDEBUG)
            return
        meta_api_result = json.loads(meta_api_get.text)
        title_contents = []
        for i in noname_contents:
            title_code = i['title_code']
            name = next((meta['display_name'] for meta in meta_api_result
                         if meta['title_code'] == title_code),
                        {'display_name': ''})
            thumbnail = i['thumbnail']
            title_contents.append(TitleContent(title_code, name, thumbnail))
        return title_contents

    @property
    async def _browser(self) -> Browser:
        """
        ブラウザ

        Returns
        -------
        result : Browser
            ブラウザ
        """
        if self.__browser is None:
            browser_path = cwebdriverinstaller.CWebDriverInstaller.chrome_browser_path(
            )
            self.__browser = await launch({
                'args': ['--no-sandbox'],
                'executablePath': browser_path,
                'handleSIGINT': False,
                'handleSIGTERM': False,
                'handleSIGHUP': False,
            })
        return self.__browser

    @property
    async def _page(self) -> Page:
        if self.__page is None:
            browser = await self._browser
            page = await browser.newPage()
            if self.__browser_default_user_agent is None:
                self.__browser_default_user_agent = await page.evaluate(
                    '() => navigator.userAgent')
            user_agent = UnextAnimeFreeServiceProvider.__CUSTOM_USER_AGENT + ' ' + xbmc.getUserAgent(
            ) + ' ' + self.__browser_default_user_agent
            await page.setUserAgent(user_agent)
            self.__page = page
        return self.__page

    @property
    def _session(self) -> requests.Session:
        """
        セッション

        Returns
        -------
        result : requests.Session
            セッション
        """
        if self.__session is None:
            self.__session = requests.Session()
        return self.__session

    __CUSTOM_USER_AGENT: str = 'under-nex-trap-animefree/0.0.1'
    """
    カスタムUser-Agent
    """

    __HEADERS: dict[str, str] = {
        'User-Agent':
        __CUSTOM_USER_AGENT + ' ' + requests.utils.default_user_agent() + ' ' +
        xbmc.getUserAgent()
    }
    """
    User-Agent改変用ヘッダー
    """

    __TITLE_CODE_FROM_URL: re.Pattern = re.compile(r'SID\d+')
    """
    URLからタイトルコードを取得する正規表現
    """

    @staticmethod
    def __get_title_code_from_url(url: str) -> str:
        """
        URLからタイトルコードを取得する

        Parameters
        -------
        url : str
            URL

        Returns
        -------
        result : str
            タイトルコード
        """
        title_code = UnextAnimeFreeServiceProvider.__TITLE_CODE_FROM_URL.search(
            url).group(0)
        return title_code

    async def __aenter__(self) -> UnextAnimeFreeServiceProvider:
        """
        With句開始

        Returns
        -------
        result : UnextAnimeFreeServiceProvider
            自身
        """
        return self

    async def __aexit__(self, exception_type, exception_value,
                        traceback) -> bool:
        """
        With句終了

        Returns
        -------
        result : bool
            True:例外を再スローしない, False:例外を再スローする
        """
        await self.dispose()
        return False
コード例 #14
0
If we are unit testing, change logs -> print

In other files, minimal code to make this work is:

# Small hack to allow for unit testing - see common.py for explanation
if not xbmc.getUserAgent():
    sys.path.insert(0, '../../..') # modify this depending on actual level - assumes resources/lib/something/file.py

from resources.lib.store import Store
from resources.lib.common import *
..etc

"""

unit_testing = False
if not xbmc.getUserAgent():

    xbmc = None
    unit_testing = True
    KODI_VERSION = 'N/A'

    print("\nNo user agent, must be unit testing.\n")

    def log(message, exception_instance=None, level=None):
        print(f'DEBUG: {message}')
        if exception_instance:
            print(f'EXCPT: {traceback.format_exc(exception_instance)}')


else: