def main(): term = Terminal() term.stream.write(term.clear()) term.stream.write(term.move(0, 0)) key, secret = os.getenv('CRYPTOPIA_MAIN_KEY'), os.getenv( 'CRYPTOPIA_MAIN_SECRET') api = ApiClient(key, secret) symbols = api.get_ticker() print(symbols.keys()) with term.cbreak(): val = '' while val.lower() != 'q': val = term.inkey(timeout=5) if not val: # timeout print("It sure is quiet in here ...") elif val.is_sequence: print("got sequence: {0}.".format( (str(val), val.name, val.code))) elif val: if val == 'r': roc = TA.ROC(pd.DataFrame(), period=3)[-1] print(roc)
def main(): ## Pull PostgreSQL information from the environment pg_passwd = os.environ['POSTGRES_ENV_POSTGRES_PASSWORD'] pg_port = os.environ['POSTGRES_PORT_5432_TCP_PORT'] pg_addr = os.environ['POSTGRES_PORT_5432_TCP_ADDR'] pg_dn = 'postgresql://*****:*****@%s:%s/postgres' % (pg_passwd, pg_addr, pg_port) ## Create the sqlalchemy session engine = create_engine(pg_dn) Session = sessionmaker() Session.configure(bind=engine) session = Session() ## Flushing after every bulk_save_objects for sake of sanity with debugging ## and unpredictable timing ## Using bulk_save_objects instead of add_all for sake of duplicate primary keys ## merge could also be used in this case ## Truncate tables each run (this order necessary for foreign key constraints) sys.stdout.write('Truncating Tables\n') sys.stdout.flush() session.query(Stop).delete() session.query(Route).delete() session.query(Agency).delete() ## Load all the agencies from the api and create model objects for them sys.stdout.write('Loading Agencies\n') sys.stdout.flush() agencies = ApiClient.get_agencies() session.bulk_save_objects(agencies) session.flush() progress_widgets = ['Saving: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()] ## For each of the agencies loaded, gather the routes sys.stdout.write('Loading routes for all agencies\n') sys.stdout.flush() pbar = ProgressBar(term_width=50, widgets=progress_widgets) for a in pbar(agencies): for r in ApiClient.get_routes(a.id): session.merge(r) session.flush() sys.stdout.write('\n') sys.stdout.flush() ## For each of the agencies loaded, gather the stops sys.stdout.write('Loading stops for all agencies\n') sys.stdout.flush() pbar = ProgressBar(term_width=50, widgets=progress_widgets) for a in pbar(agencies): for s in ApiClient.get_stops(a.id): session.merge(s) session.flush()
def __init__(self, **options): ''' 备份指定用户的饭否消息数据 ''' logger.info('Backup.init()', options) self._parse_options(**options) self.api = ApiClient(False) self.token = utils.load_account_info(self.username) self.user = None self.target_id = None self.db = None self.cancelled = False self.total = 0 self.user_total = 0 self.photo_total = 0
def __init__(self, apiKey, softId=None, callback=None, defaultTimeout=120, recaptchaTimeout=600, pollingInterval=10, server='2captcha.com'): self.API_KEY = apiKey self.soft_id = softId self.callback = callback self.default_timeout = defaultTimeout self.recaptcha_timeout = recaptchaTimeout self.polling_interval = pollingInterval self.api_client = ApiClient(post_url=str(server)) self.max_files = 9 self.exceptions = SolverExceptions
def __init__(self, *args, **kwargs): super(NetworkPredictHandler, self).__init__(*args, **kwargs) self.client = ApiClient(self.settings['api'])
class Backup(object): def __init__(self, **options): ''' 备份指定用户的饭否消息数据 ''' logger.info('Backup.init()', options) self._parse_options(**options) self.api = ApiClient(False) self.token = utils.load_account_info(self.username) self.user = None self.target_id = None self.db = None self.cancelled = False self.total = 0 self.user_total = 0 self.photo_total = 0 def _parse_options(self, **options): ''' username - 用户帐号(可选) password - 用户密码(可选) output - 数据保存目录 target - 目标用户ID include_user - 是否备份好友资料 include_photo - 是否备份相册照片 ''' self.username = options.get('username') self.password = options.get('password') self.auth_mode = self.username and self.password self.target = options.get('target') self.output = os.path.abspath( options.get('output') or os.path.join('output')) self.include_user = options.get('include_user') self.include_photo = options.get('include_photo') def _precheck(self): if self.token: print('载入{1}的本地登录信息{0}'.format( self.token['oauth_token'], self.username)) self.api.set_oauth_token(self.token) if self.auth_mode: if self.api.is_verified(): self.token = self.api.oauth_token self.user = self.api.user else: self.token = self.api.login(self.username, self.password) self.user = self.api.user print('保存{1}的登录信息{0}'.format( self.token['oauth_token'], self.username)) utils.save_account_info(self.username, self.token) if not self.target and not self.user: print('没有指定备份的目标用户') return self.target_id = self.target or self.user['id'] def stop(self): print('收到终止备份的命令,即将停止...') self.cancelled = True def start(self): self._precheck() if not self.target_id: return try: self.target_user = self.api.get_user(self.target_id) except ApiError, e: if e.args[0] == 404: print('你指定的用户{0}不存在'.format(self.target_id)) self.target_user = None if not self.target_user: print( '无法获取用户{0}的信息'.format(self.target_id)) return print('用户{0}共有{1}条消息,{2}个好友'.format( self.target_user['id'], self.target_user['statuses_count'], self.target_user['friends_count'])) if not os.path.exists(self.output): os.mkdir(self.output) print('开始备份用户{0}的消息...'.format(self.target_id)) db_file = os.path.abspath( '{0}/{1}.db'.format(self.output, self.target_id)) print('保存路径:{0}'.format(self.output)) self.db = DB(db_file) db_count = self.db.get_status_count() if db_count: print('发现数据库已备份消息{0}条'.format(db_count)) # first ,check new statuses self._fetch_newer_statuses() # then, check older status self._fetch_older_statuses() if self.include_photo: # check user photos print('开始备份用户{0}的相册照片...'.format(self.target_id)) start = time.time() self._fetch_photos_multi() elasped = time.time()-start print('备份用户{0}的照片共耗时{1}秒'.format(self.target_id, elasped)) if self.include_user: # check user followings print('开始备份用户{0}的好友资料...'.format(self.target_id)) self._fetch_followings() self._render_statuses() self._report() if self.cancelled: print('本次备份已终止') else: print('本次备份已完成') self.db.close()
def __init__(self, reader, writer, token): super().__init__(Platform(manifest['platform']), manifest['version'], reader, writer, token) self._api = ApiClient(self.store_credentials, self.lost_authentication) self._local = LocalClient()
class PluginOsu(Plugin): def __init__(self, reader, writer, token): super().__init__(Platform(manifest['platform']), manifest['version'], reader, writer, token) self._api = ApiClient(self.store_credentials, self.lost_authentication) self._local = LocalClient() # const game info async def get_owned_games(self) -> List[Game]: return [ Game(OSU, OSU, None, LicenseInfo(LicenseType.OtherUserLicense)) ] async def get_os_compatibility(self, game_id, context): return OSCompatibility.Windows # | OSCompatibility.MacOS # support for windows for now # authentication async def _auth(self, tokens: dict): self._api.set_credentials(tokens) return Authentication(self._api.user_id, (await self._api.get_me())['username']) async def authenticate(self, stored_credentials=None ) -> Union[Authentication, NextStep]: if stored_credentials is not None: return await self._auth(stored_credentials) return NextStep( 'web_session', { "window_title": "Login to osu!", "window_width": 570, "window_height": 700, "start_uri": OAuthClient.START_URL, "end_uri_regex": '^' + re.escape(OAuthClient.END_URL) + r'\?.*token_type=Bearer.*' }) async def pass_login_credentials(self, step: str, credentials: Dict[str, str], cookies: List[Dict[str, str]]) \ -> Union[NextStep, Authentication]: query_string = parse.urlsplit(credentials['end_uri']).query tokens = dict(parse.parse_qsl(query_string)) return await self._auth(tokens) # API features async def get_unlocked_achievements(self, game_id, context): me = await self._api.get_me() return [ Achievement(achievement_id=medal['achievement_id'], unlock_time=int( datetime.fromisoformat( medal['achieved_at']).timestamp())) for medal in me.get('user_achievements', []) ] async def get_game_time(self, game_id, context): me = await self._api.get_me() seconds_played = me['statistics']['play_time'] return GameTime(OSU, seconds_played // 60, last_played_time=None) async def get_friends(self): return [ UserInfo(str(f['id']), f['username'], f.get('avatar_url'), 'https://osu.ppy.sh/users/' + str(f['id'])) for f in await self._api.get_friends() if not f['is_bot'] ] async def prepare_user_presence_context(self, user_id_list): return { str(f['id']): PresenceState.Online for f in await self._api.get_friends() if f['is_online'] } async def get_user_presence(self, user_id, context): state = context.get(user_id, PresenceState.Offline) return UserPresence(state) # local game management async def get_local_games(self) -> List[LocalGame]: state = LocalGameState.None_ if self._local.is_installed: state |= LocalGameState.Installed if self._local.is_running: state |= LocalGameState.Running return [LocalGame(OSU, state)] async def install_game(self, game_id): install_link = 'https://m1.ppy.sh/r/osu!install.exe' installer_path = pathlib.PurePath( tempfile.gettempdir()) / install_link.split('/')[-1] try: async with aiofiles.open(installer_path, mode="wb") as installer_bin: await installer_bin.write(await self._api.get_file(install_link)) except Exception as e: logger.error(repr(e)) webbrowser.open('https://osu.ppy.sh/home/download') else: await self._local.install(installer_path) if self._local.is_installed: self.update_local_game_status( LocalGame(OSU, LocalGameState.Installed)) async def launch_game(self, game_id): process = await self._local.launch() self.update_local_game_status( LocalGame(OSU, LocalGameState.Installed | LocalGameState.Running)) await process.wait() self.update_local_game_status(LocalGame(OSU, LocalGameState.Installed))
metrics.info('flask_app_info', 'Application info', version=os.environ.get('GIT_COMMIT') or 'unknown') metrics.info('flask_app_built_at', 'Application build timestamp').set( float(os.environ.get('BUILD_TIMESTAMP') or '0')) CORS(app, origins=read_configuration('CORS_ORIGINS', '/var/secrets/secrets.env', default='http://*****:*****@app.route('/repos/<username>') @cache.memoize(timeout=30 * 60) def list_repos(username): logger.info('Listing repositories for user %s', username) results = list()
def get_api_client(): return ApiClient(token=os.environ.get('GITHUB_TOKEN', _get_cached_token()))
def exec_command(cmd): cmd_result = call(cmd, shell=True) if type(cmd_result) is int and cmd_result is not 0: exit(cmd_result) if __name__ == '__main__': with open('./conf.d/config.json', 'r') as config_file: config = json.load(config_file) # configure time zone os.environ['TZ'] = config.pop('timezone', '') time.tzset() ac = ApiClient(**config['storage']) ac.setup() notification = Notify(config.pop('notification', None)) if not ac.check_available_space(): notification.send( f'Not enough space for uploading backup "{config["name"]}"') print_log('CRITICAL: Not enough space for uploading backup') exit() if 'run_before' in config: print_log('Execution \'run_before\' command is started') exec_command(config['run_before']) # create backup path_to_backup_file = make_backup(**config)
logging.basicConfig( format='%(asctime)s [%(levelname)s] %(module)s.%(funcName)s - %(message)s') logger = logging.getLogger('googleplay-proxy') logger.setLevel(logging.INFO) _api_type = read_configuration('API_TYPE', '/var/secrets/secrets.env', default='api') if _api_type == 'api': api = ApiClient(android_id=read_configuration('ANDROID_ID', '/var/secrets/secrets.env'), username=read_configuration('GOOGLE_USERNAME', '/var/secrets/secrets.env'), password=read_configuration('GOOGLE_PASSWORD', '/var/secrets/secrets.env'), max_login_retries=int( read_configuration('MAX_LOGIN_RETRIES', '/var/secrets/secrets.env', default='10'))) elif _api_type == 'scraper': api = Scraper(cache_max_age=int( read_configuration( 'MAX_CACHE_AGE', '/var/secrets/secrets.env', default=24 * 60 * 60))) else: logger.error('Invalid API type "%s" (valid ones are: "api" and "scraper")', os.environ.get('API_TYPE')) exit(1)
class TwoCaptcha(): def __init__(self, apiKey, softId=None, callback=None, defaultTimeout=120, recaptchaTimeout=600, pollingInterval=10, server='2captcha.com'): self.API_KEY = apiKey self.soft_id = softId self.callback = callback self.default_timeout = defaultTimeout self.recaptcha_timeout = recaptchaTimeout self.polling_interval = pollingInterval self.api_client = ApiClient(post_url=str(server)) self.max_files = 9 self.exceptions = SolverExceptions def normal(self, file, **kwargs): ''' Wrapper for solving normal captcha (image) Required: file (image or base64) Optional params: phrase numeric minLen maxLen phrase caseSensitive calc lang hintText hintImg softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' method = self.get_method(file) result = self.solve(**method, **kwargs) return result def text(self, text, **kwargs): ''' Wrapper for solving text captcha Required: text Optional params: lang softId callback ''' result = self.solve(text=text, method='post', **kwargs) return result def recaptcha(self, sitekey, url, version='v2', enterprise=0, **kwargs): ''' Wrapper for solving recaptcha (v2, v3) Required: sitekey url Optional params: invisible version enterprise action score softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' params = { 'googlekey': sitekey, 'url': url, 'method': 'userrecaptcha', 'version': version, 'enterprise': enterprise, **kwargs, } result = self.solve(timeout=self.recaptcha_timeout, **params) return result def funcaptcha(self, sitekey, url, **kwargs): ''' Wrapper for solving funcaptcha Required: sitekey url Optional params: surl userAgent softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) **{'data[key]': 'anyStringValue'} ''' result = self.solve(publickey=sitekey, url=url, method='funcaptcha', **kwargs) return result def geetest(self, gt, challenge, url, **kwargs): ''' Wrapper for solving geetest captcha Required: gt challenge url Optional params: apiServer softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' result = self.solve(gt=gt, challenge=challenge, url=url, method='geetest', **kwargs) return result def hcaptcha(self, sitekey, url, **kwargs): ''' Wrapper for solving hcaptcha Required: sitekey url Optional params: invisible data softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' result = self.solve(sitekey=sitekey, url=url, method='hcaptcha', **kwargs) return result def keycaptcha(self, s_s_c_user_id, s_s_c_session_id, s_s_c_web_server_sign, s_s_c_web_server_sign2, url, **kwargs): ''' Wrapper for solving Required: s_s_c_user_id s_s_c_session_id s_s_c_web_server_sign s_s_c_web_server_sign2 url Optional params: softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' params = { 's_s_c_user_id': s_s_c_user_id, 's_s_c_session_id': s_s_c_session_id, 's_s_c_web_server_sign': s_s_c_web_server_sign, 's_s_c_web_server_sign2': s_s_c_web_server_sign2, 'url': url, 'method': 'keycaptcha', **kwargs, } result = self.solve(**params) return result def capy(self, sitekey, url, **kwargs): ''' Wrapper for solving capy Required: sitekey url Optional params: softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' result = self.solve(captchakey=sitekey, url=url, method='capy', **kwargs) return result def grid(self, file, **kwargs): ''' Wrapper for solving grid captcha (image) Required: file (image or base64) Optional params: rows cols previousId canSkip lang hintImg hintText softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' method = self.get_method(file) params = { 'recaptcha': 1, **method, **kwargs, } result = self.solve(**params) return result def canvas(self, file, **kwargs): ''' Wrapper for solving canvas captcha (image) Required: file (image or base64) Optional params: previousId canSkip lang hintImg hintText softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' if not ('hintText' in kwargs or 'hintImg' in kwargs): raise ValidationException( 'parameters required: hintText and/or hintImg') method = self.get_method(file) params = { 'recaptcha': 1, 'canvas': 1, **method, **kwargs, } result = self.solve(**params) return result def coordinates(self, file, **kwargs): ''' Wrapper for solving coordinates captcha (image) Required: file (image or base64) Optional params: hintImg hintText lang softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' method = self.get_method(file) params = { 'coordinatescaptcha': 1, **method, **kwargs, } result = self.solve(**params) return result def rotate(self, files, **kwargs): ''' Wrapper for solving rotate captcha (image) Required: files (images) Optional params: angle lang hintImg hintText softId callback proxy = {'type': 'HTTPS', 'uri': 'login:password@IP_address:PORT'}) ''' if isinstance(files, str): file = self.get_method(files)['file'] result = self.solve(file=file, method='rotatecaptcha', **kwargs) return result elif isinstance(files, dict): files = list(files.values()) files = self.extract_files(files) result = self.solve(files=files, method='rotatecaptcha', **kwargs) return result def solve(self, timeout=0, polling_interval=0, **kwargs): ''' sends captcha, receives result Parameters ---------- timeout : float polling_interval : int **kwargs : all captcha params Returns ------- result : string ''' id_ = self.send(**kwargs) result = {'captchaId': id_} if self.callback is None: timeout = float(timeout or self.default_timeout) sleep = int(polling_interval or self.polling_interval) code = self.wait_result(id_, timeout, sleep) result.update({'code': code}) return result def wait_result(self, id_, timeout, polling_interval): max_wait = time.time() + timeout while time.time() < max_wait: try: return self.get_result(id_) except NetworkException: time.sleep(polling_interval) raise TimeoutException(f'timeout {timeout} exceeded') def get_method(self, file): if not file: raise ValidationException('File required') if not '.' in file and len(file) > 50: return {'method': 'base64', 'body': file} if not os.path.exists(file): raise ValidationException(f'File not found: {file}') return {'method': 'post', 'file': file} def send(self, **kwargs): params = self.default_params(kwargs) params = self.rename_params(params) params, files = self.check_hint_img(params) response = self.api_client.in_(files=files, **params) if not response.startswith('OK|'): raise ApiException(f'cannot recognize response {response}') return response[3:] def get_result(self, id_): response = self.api_client.res(key=self.API_KEY, action='get', id=id_) if response == 'CAPCHA_NOT_READY': raise NetworkException if not response.startswith('OK|'): raise ApiException(f'cannot recognize response {response}') return response[3:] def balance(self): ''' get my balance Returns ------- balance : float ''' response = self.api_client.res(key=self.API_KEY, action='getbalance') return float(response) def report(self, id_, correct): ''' report of solved captcha: good/bad Parameters ---------- id_ : captcha ID correct : True/False Returns ------- None. ''' rep = 'reportgood' if correct else 'reportbad' self.api_client.res(key=self.API_KEY, action=rep, id=id_) return def rename_params(self, params): replace = { 'caseSensitive': 'regsense', 'minLen': 'min_len', 'maxLen': 'max_len', 'hintText': 'textinstructions', 'hintImg': 'imginstructions', 'url': 'pageurl', 'score': 'min_score', 'text': 'textcaptcha', 'rows': 'recaptcharows', 'cols': 'recaptchacols', 'previousId': 'previousID', 'canSkip': 'can_no_answer', 'apiServer': 'api_server', 'softId': 'soft_id', 'callback': 'pingback', } new_params = { v: params.pop(k) for k, v in replace.items() if k in params } proxy = params.pop('proxy', '') proxy and new_params.update({ 'proxy': proxy['uri'], 'proxytype': proxy['type'] }) new_params.update(params) return new_params def default_params(self, params): params.update({'key': self.API_KEY}) callback = params.pop('callback', self.callback) soft_id = params.pop('softId', self.soft_id) if callback: params.update({'callback': callback}) if soft_id: params.update({'softId': soft_id}) self.has_callback = bool(callback) return params def extract_files(self, files): if len(files) > self.max_files: raise ValidationException( f'Too many files (max: {self.max_files})') not_exists = [f for f in files if not (os.path.exists(f))] if not_exists: raise ValidationException(f'File not found: {not_exists}') files = {f'file_{e+1}': f for e, f in enumerate(files)} return files def check_hint_img(self, params): hint = params.pop('imginstructions', None) files = params.pop('files', {}) if not hint: return params, files if not '.' in hint and len(hint) > 50: return params, files if not os.path.exists(hint): raise ValidationException(f'File not found: {hint}') if not files: files = {'file': params.pop('file', {})} files.update({'imginstructions': hint}) return params, files
def api_bear() -> ApiClient: """API fixture""" return ApiClient(base_url=DockerConstants.BASE_URL)
class Backup(object): def __init__(self, **options): ''' 备份指定用户的饭否消息数据 ''' logger.info('Backup.init()', options) self._parse_options(**options) self.api = ApiClient(False) self.token = utils.load_account_info(self.username) self.user = None self.target_id = None self.db = None self.cancelled = False self.total = 0 self.user_total = 0 self.photo_total = 0 def _parse_options(self, **options): ''' username - 用户帐号(可选) password - 用户密码(可选) output - 数据保存目录 target - 目标用户ID include_user - 是否备份好友资料 include_photo - 是否备份相册照片 ''' self.username = options.get('username') self.password = options.get('password') self.auth_mode = self.username and self.password self.target = options.get('target') self.output = os.path.abspath( options.get('output') or os.path.join('output')) self.include_user = options.get('include_user') self.include_photo = options.get('include_photo') def _precheck(self): if self.token: print('载入{1}的本地登录信息{0}'.format(self.token['oauth_token'], self.username)) self.api.set_oauth_token(self.token) if self.auth_mode: if self.api.is_verified(): self.token = self.api.oauth_token self.user = self.api.user else: self.token = self.api.login(self.username, self.password) self.user = self.api.user print('保存{1}的登录信息{0}'.format(self.token['oauth_token'], self.username)) utils.save_account_info(self.username, self.token) if not self.target and not self.user: print('没有指定备份的目标用户') return self.target_id = self.target or self.user['id'] def stop(self): print('收到终止备份的命令,即将停止...') self.cancelled = True def start(self): self._precheck() if not self.target_id: return try: self.target_user = self.api.get_user(self.target_id) except ApiError, e: if e.args[0] == 404: print('你指定的用户{0}不存在'.format(self.target_id)) self.target_user = None if not self.target_user: print('无法获取用户{0}的信息'.format(self.target_id)) return print('用户{0}共有{1}条消息,{2}个好友'.format(self.target_user['id'], self.target_user['statuses_count'], self.target_user['friends_count'])) if not os.path.exists(self.output): os.mkdir(self.output) print('开始备份用户{0}的消息...'.format(self.target_id)) db_file = os.path.abspath('{0}/{1}.db'.format(self.output, self.target_id)) print('保存路径:{0}'.format(self.output)) self.db = DB(db_file) db_count = self.db.get_status_count() if db_count: print('发现数据库已备份消息{0}条'.format(db_count)) # first ,check new statuses self._fetch_newer_statuses() # then, check older status self._fetch_older_statuses() if self.include_photo: # check user photos print('开始备份用户{0}的相册照片...'.format(self.target_id)) start = time.time() self._fetch_photos_multi() elasped = time.time() - start print('备份用户{0}的照片共耗时{1}秒'.format(self.target_id, elasped)) if self.include_user: # check user followings print('开始备份用户{0}的好友资料...'.format(self.target_id)) self._fetch_followings() self._render_statuses() self._report() if self.cancelled: print('本次备份已终止') else: print('本次备份已完成') self.db.close()
def get_real_api_client(): details = get_access_details() return ApiClient(android_id=os.environ.get('ANDROID_ID', details.get('androidId')), username=os.environ.get('GOOGLE_USERNAME', details.get('username')), password=os.environ.get('GOOGLE_PASSWORD', details.get('password')))
import math import time import datetime import json import redis import logging import numpy as np import pandas as pd import utils from api import ApiClient from parser import YouTubeHistoryParser api_client = ApiClient() def query_api(queries): print('to query for {0} videos'.format(len(queries))) queries = list(queries) queries = utils.chunks(queries, 50) result = {} for query in queries: remaining_queries = set(query) response = api_client.request_video_list(query) if type(response) == str: #An error occured return response
def api(store_credentials, auth_lost): return ApiClient(store_credentials, auth_lost)