async def fbgraph_query(self, resource, extra_params={}, credentials=None, version_segment=API_3_3): """ graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token} """ params = {} if credentials is None: params['access_token'] = self.access_token if credentials: params['access_token'] = credentials.get('access_token') params.update(extra_params) async with aiohttp.ClientSession() as session: url = f'https://graph.facebook.com/{version_segment}' + resource logger.debug(f'quering {url}', params=params) async with session.get(url, params=params) as response: if response.status == 200: return await response.json() logger.error('fbgraph_query error', status=response.status, text=(await response.text()))
async def ws_sender(ws): subscription = state.logs_reader() while True: try: msg = await subscription.get() if msg is None: break tstr = datetime.datetime.utcfromtimestamp( msg.ts / 1000).strftime("%m%d %H:%m:%S.%s")[:18] data = { 'id': msg.id, 'cid': msg.cid, 'cname': msg.name, 'time': tstr, 'ts': msg.ts, 'source': msg.source, 'data': msg.message } await ws.send_str(ujson.dumps(data)) await rpc.notify('logs', 'write', msg=msg) except CancelledError: logger.debug('ws writer closed') break except Exception: logger.exception('ex') break
async def self_test(self): test = await self.fbgraph_query('/6510235916185894912') logger.debug('self_test 1', result=test) test = await self.debug_token( 'EAAOJ05PIHRYBAAd5GdY9hZAGJgnVGq8O68ZBFTMn6OzSoCW2WL2aQVooQxfPGZCIhH7Vnid3DKRtVwZBJtCrH0MDbaIbe50j4G9U6ZBvVrh26DZC4noZBANIUprk4kuPt3vCLfpXbb6KQaY7JEx8i3QtvZAZBPhZCZBdZCmwcIP0nXVk0vM9LrmKUfGXeCC4ZCVn3arUY8UZAp7P9LdAZDZD' ) logger.debug('self_test 2', result=test)
async def touch(self, uid): if uid in self.users: diff = ms() - self.users[uid].act if diff > 2000: logger.debug('touching user', uid=uid, df=diff) self.users[uid].act = ms() await self.save_user(uid)
def check_key(params, settings): pid_input = str(params.get('projectId', '')) pid_config = str(settings.get('projectIdKey', '')) pids_eq = pid_input == pid_config if not pids_eq: logger.debug(f'projectId not match: {pid_config}!={pid_input}', st=str(type(pid_config)), inp=str(type(pid_input))) return pid_config and pids_eq
async def main(data, **params): data = pdict.from_dict(data) logger.debug('received message', **data) if data.message: await scheduler.spawn(handle_msg(data)) return {}
async def api_call(url, params=None, json=None, method='get'): async with aiohttp.ClientSession() as session: method = getattr(session, method.lower()) async with method(url, json=json, params=params) as res: logger.debug(f'quering {url}', status=res.status) if res.status == 204: return {} if res.status == 200: return await res.json()
async def _do_run_service(self, name): svc = await self.get(name) env = deepcopy(self._shared_config.get('env', {})) env.update(svc.env) await dock.run_container(name, env=env, **svc.build_options) await band_config.set_add(STARTED_SET, name) logger.debug('service. saving config', svc=dict(bo=svc.build_options, e=svc.env)) svc.save_config() await self.resolve_docstatus(name)
async def do_query(url, params, json=None): method = 'post' if json else 'get' async with aiohttp.ClientSession() as session: async with session.request(method, url, params=params, json=json) as resp: resp_data = await resp.json() if resp.status == 200: logger.debug('resp data', rd=resp_data, code=resp.status) return resp_data else: logger.error('wrong response', rd=resp_data, code=resp.status)
async def get(self, name, **kwargs): params = kwargs.pop('params', pdict()) positions = [] # Container env envs = [] if params.env: envs.append(params.env) if params.get('pos') and is_valid_pos(params.pos): positions.append(params.pos) if name not in self._state: logger.debug('loading state', name=name) config = await self.load_config(name) meta = await image_navigator.image_meta(name) svc = ServiceState(name=name, manager=self) if config: if config.get('env'): envs.append(config['env']) if config.get('pos') and is_valid_pos(config['pos']): positions.append(config['pos']) if meta: svc.set_meta(meta) if meta.env: envs.append(meta.env) if meta.get('pos') and is_valid_pos(meta['pos']): positions.append(meta['pos']) positions.append(self.grid.default_pos) self._state[name] = svc svc = self._state[name] # env variables if len(envs): svc.set_env(merge_dicts(*envs)) # passed build options if params.build_opts: svc.set_build_opts(**params.build_opts) # position allocation if len(positions): # TODO: pass list of positions pos = positions.pop(0) logger.debug('set_pos', p=pos) await self.set_pos(name, pos, svc=svc) return svc
def auth_link(self, state=None, auth_type='rerequest'): login_params = { 'scope': ','.join(self.scopes), 'client_id': self.app_id, 'redirect_uri': self.redirect_uri, 'auth_type': auth_type, 'state': state } login_url = f'https://www.facebook.com/v3.2/dialog/oauth?' + urlencode( login_params) logger.debug('fb_redir', url=self.redirect_uri) return login_url
def clean_status(self): logger.debug('restoring state', name=self.name) self._meta = pdict() self._app = pdict() self._app_ts = None self._status_override = None self._dock = pdict() self._dock_ts = None self._methods = [] self._managed = False self._protected = False self._persistent = False self._native = False
def allocate(self, name, col, row): """ Allocating dashboard position for container close to wanted """ occupied = self._occupied(exclude=name) for icol, irow in self._space_walk(int(col), int(row)): key = f"{icol}x{irow}" if key not in occupied: logger.debug(f'Allocatted position', name=name, pos=f"{col}x{row}", occupied=occupied, allocated=f"{icol}x{irow}") return dict(col=icol, row=irow)
async def send_sms(to=None, msg=None, to_phone=None): to = to or to_phone if not to or not msg: raise Exception('wronds params') logger.info(f'sending sms to {to}') curr_count = await redis.get(to + str(date.today())) curr_count = int(curr_count or 0) if to != '79261244141' and curr_count >= 3: logger.info('too many requests') return {'error': 'too many requests'} await redis.increx(to, 60 * 60 * 24) params = dict(sender=settings.sender, to=to, msg=msg) result = await api_call(settings.endpoint.format(**params)) logger.debug('send_sms', p=params, r=result) return result
async def status_checker(): while True: curr_date_in_ch = await get_actual_server_status() if curr_date_in_ch != None: diff_in_min = ((datetime.datetime.now() + datetime.timedelta(hours=3)) - curr_date_in_ch).seconds / 60 logger.debug('Actual difference in data is {}'.format(diff_in_min)) if diff_in_min > 15: await bot.send_message(MY_USER_ID, "!!!! Данные на сервере не актуальны !!!! \n Последняя запись от: {}".format(curr_date_in_ch.strftime('%d-%m-%Y %H:%M:%S'))) else: await bot.send_message(MY_USER_ID, "Боту хреново! Спаси бота!") # Wait explicit time next_at = arrow.utcnow().shift(minutes=+15) wait_secs = next_at.timestamp - arrow.utcnow().timestamp logger.debug("waiting {} seconds".format(wait_secs)) await asyncio.sleep(wait_secs)
def uniform_filter(items, field=None, val=None): logger.debug('uniform_filter', field=field, val=val) results = [] for item in (items.values() if isinstance(items, dict) else items): if not field: results.append(item) else: prop = item.get(field, None) print(item, prop, val) if prop is not None: if isinstance(prop, list) or isinstance(prop, set): if val in prop: results.append(item) else: if val == prop: results.append(item) return results
async def mp_get_profile(recipient): """ Messenger Platform get Profile """ cahed_id = str(recipient) cached_profile = profiles.get(cahed_id) if cached_profile: return cached_profile url = f'https://graph.facebook.com/{recipient}' query = { 'fields': 'first_name,last_name,profile_pic', 'access_token': cfg.fb.app_page_token } resp = await do_query(url, query) if resp: profiles[cahed_id] = resp logger.debug('mp_get_profile', resp=resp) return resp
async def account_linking(data, **params): """ https://bolt.rstat.org/alena/fblogin? account_linking_token=ARQPHBqhe51U6rtHHhRCiyQDNF8eoMgRG8GhLtgbzb-75nDP4lS9CPElE7Kg2R70qLcW57hcnXiil4HOKFtFC6ZMn4i6XDboP9AzbtHyaHkjcw& redirect_uri=https%3A%2F%2Ffacebook.com%2Fmessenger_platform%2Faccount_linking%2F%3Faccount_linking_token%3DARQPHBqhe51U6rtHHhRCiyQDNF8eoMgRG8GhLtgbzb-75nDP4lS9CPElE7Kg2R70qLcW57hcnXiil4HOKFtFC6ZMn4i6XDboP9AzbtHyaHkjcw ... phone """ raw_phone = data.get('phone') code = data.get('code') account_linking_token = data.get('account_linking_token') id_req = None if account_linking_token: # Temp Service id; auth code auth_code = xhash(account_linking_token) sid = ( 'fblink', auth_code, ) if not code and raw_phone: # request confirmation id_req = await id_phone_identify(raw_phone, sid) logger.debug('id req', resp=id_req) if id_req and 'success' in id_req: return {'phone_status': 1} if code: # confirm id_req = await id_phone_confirm(sid, code, False) logger.debug('id req', resp=id_req) # Success auth if id_req and 'success' in id_req: return { 'phone_status': 1, 'code_status': 1, 'auth_code': auth_code } if id_req and 'error' in id_req: return id_req logger.warn('smth went wrong', id_req=id_req) return {}
async def wh_handler(data): if data.get('object') == 'page': for e in data.get('entry', []): for c in e.get('changes', []): field = c.pop('field', None) value = c.pop('value', {}) handler = handlers.get(field) if handler: await handler(value) for m in e.get('messaging', []): logger.debug('messaging -> item', m=m) # {'recipient': {'id': '1040392926136659'}, 'timestamp': 1554966532345, 'sender': {'id': '1921281307989859'}, 'account_linking': {'authorization_code': 'ab3936a2662e5c6a', 'status': 'linked'}} sender_id = m.get('sender', {}).get('id') m['profile'] = await mp_get_profile(sender_id) if m.get('message'): await rpc.notify('digitalgodbot', 'fb_message', item=m) if m.get('account_linking'): # 'account_linking': {'authorization_code': 'ab3936a2662e5c6a', 'status': 'linked'} await rpc.notify('digitalgodbot', 'fb_link', item=m)
async def events_reader(self, docker, logs): subscriber = docker.events.subscribe() for bc in await self.containers(inband=False, status='running'): container = bc.container await scheduler.spawn( self.logs_reader(docker, container, logs, bc.name, bc.id)) logger.debug(f'creating logger for {bc.name}') while True: event = await subscriber.get() if event is None: break if event['Action'] == 'start' and event['Type'] == 'container': cid = event['Actor']['ID'] container = await docker.containers.get(cid) name = event['Actor']['Attributes']['name'] await scheduler.spawn( self.logs_reader(docker, container, logs, name, cid))
async def confirm(service_id, code): """ Finish validation and save match -- confirm(service_id:ServiceId, code:str) """ logger.debug(f'confirm called {service_id}, {code}') if service_id and code: sid = ServiceId(*service_id) sid_str = str(sid) stored_code = state.codes.pop(sid_str, None) logger.debug( f'{sid} confirmation, checking code for phone {stored_code.service_id}. given {code}' ) if stored_code and stored_code.check(code): logger.debug('confirmed') await rpc.request('id', 'update', service_id=sid, ids=[[stored_code.service_id, ms()]]) await rpc.request('id', 'update', service_id=stored_code.service_id, ids=[[sid, ms()]]) return {'success': 1}
async def run(name, **req_params): """ Create image and run new container with service params: pos - string contains prefered coordinates, for example "2x3" (col x row) nocache - Set docker build option. By default nocache=false. auto_remove - Set docker build option. env - """ if not image_navigator.is_native(name): return 404 logger.debug('Called api.run with', params=req_params) params = RunParams(pos=ServicePostion.from_string(req_params.get('pos')), build_opts=build_options_from_req(req_params)) svc = await state.get(name, params=params) logger.info('request with params', params=params, srv_config=svc.config) svc = await state.run_service(name, no_wait=True) return svc.full_state()
async def create_image(self, img, img_options): logger.debug("Building image", n=img.name, io=img_options, path=img.path) async with img.create(img_options) as builder: progress = pdict() struct = builder.struct() last = time() async for chunk in await self.dc.images.build(**struct): if isinstance(chunk, dict): chunk = pdict.from_dict(chunk) if chunk.aux: struct.id = chunk.aux.ID logger.debug('chunk', chunk=chunk) elif chunk.status and chunk.id: progress[chunk.id] = chunk if time() - last > 1: logger.info("\nDocker build progress", progress=progress) last = time() elif chunk.stream: # logger.debug('chunk', chunk=chunk) step = re.search(r'Step\s(\d+)\/(\d+)', chunk.stream) if step: logger.debug('Docker build step ', groups=step.groups()) else: logger.debug('unknown chunk', chunk=chunk) else: logger.debug('unknown chunk type', type=type(chunk), chunk=chunk) if not struct.id: raise Exception('Build process not completed') logger.info('Docker image created', struct_id=struct.id) return img.set_data(await self.dc.images.get(img.name))
async def initialize(self): logger.info("Initializing BandConfig") self.redis_pool = await redis_factory.create_pool() logger.debug('Band state configs holder started')
async def wh_handle_mention(value): citem = value.pop('item', None) verb = value.pop('verb', None) if citem == 'post' and verb == 'add': post_id = value.pop('post_id', None) message = value.pop('message', None) logger.debug('c-item=post', value=value, post_id=post_id, message=message) post = await get_post(post_id) if not post: logger.debug('cant get post', post_id=post_id) return src_user_fb_id, src_post_id = post.get('id').split('_') logger.debug('post', p=post) user_fb_id, post_id = post.get('id').split('_') user = await digitalgod_get_user(fb_id=user_fb_id) logger.debug('user', u=user, fb_user_id=user_fb_id) if not user or not user.get('user'): logger.debug('cant get user', user_fb_id=user_fb_id, post_id=post_id) return user = user.get('user') if not user.get('phone'): logger.warn('user has no phone', user=user) return # Extracting URLs extractor = URLExtract() urls = find_urls(message) link = post.get('link') if link: urls.append(link) to_id = get_to_id(post.get('to', {}), page_id) if not len(urls): logger.debug('links not found', to_id=to_id, user=user) return page_tag = None for url in urls: if url.startswith('https://digitalgod.be'): print(url) page_tag = await digitalgod_get_page_tag(url) print(page_tag) if not page_tag or not page_tag.get('tag'): logger.debug('no page tag') return page_tag = page_tag.get('tag') logger.debug('adding tag to user', page_tag=page_tag, phone=user.get('phone'), post=post, src_user_fb_id=src_user_fb_id, user_fb_id=user_fb_id) await id_user_tags_add(service_id=['phone', user.get('phone')], tag=page_tag, lst=list_shares) event = { 'post': post, 'profile': await get_profile(src_user_fb_id), 'fb_id': src_user_fb_id } logger.debug('event', event) await rpc.notify('digitalgodbot', 'fb_share', event=event)
async def worker_work(): for i in count(): await asyncio.sleep(60 * 5) logger.debug('fb status', i=i, e=state.events)
async def __state_up(): logger.debug('Director startup worker started') await state.initialize()
async def __state_down(): logger.debug('Director shutdown worker started') await state.unload()
async def load_config(self, name): config = await band_config.load_config(name) if name == SHARED_CONFIG_KEY and config: self._shared_config = config logger.debug('loaded config', name=name, config=config) return config
async def redirback(uid, data, **params): """ """ logger.debug('fb login', u=uid, d=data, p=params) code = data.get('code') redir_state = data.get('state') if not code: return response.error('Code is absent') if not redir_state: return response.error('Invalid state') credentials = await client.exchange_code(code) if not credentials: return response.error('Couldn\'t get credentials') me = await client.me(credentials) if not me: return response.error('Couldn\'t get user info (me)') token_debug = await client.debug_token(credentials.get('access_token')) logger.debug('debug token; me resp', debresp=token_debug, meresp=me) stored_data = await id_get_redir_data(redir_state) if not stored_data or not stored_data.get('redir_data'): logger.warn('absent redir state', uid=uid, data=data) redir_data = stored_data.get('redir_data') source_sids = redir_data.get('sids') if not source_sids: logger.error('Invalid state contents', state=redir_data) return response.error('Invalid state contents') base_vars = { 'ctime': msec(), 'source': 'fbauth', 'event_id': params.get('id') } fb_params = {'access_token': credentials.get('access_token'), **base_vars} logger.debug('redir data', r=redir_data) source_sids_with_params = [( v, { **base_vars }, ) for k, v in source_sids.items()] uid_id = ( 'uid', uid, ) uid_id_with_params = ( uid_id, base_vars, ) fb_id = ( 'fb', me.get('id'), ) fb_id_with_params = ( fb_id, fb_params, ) additional_ids = [uid_id_with_params, fb_id_with_params] # save fb-to-phone,tg await id_update(fb_id, source_sids_with_params) # save uid-to-fb-tg-phone uid_sids = [*source_sids_with_params, fb_id_with_params] logger.debug('uid sids', uid_id=uid_id, usids=uid_sids) await id_update(uid_id, uid_sids) # save phone-to-uid,fb if source_sids.get('phone'): await id_update(source_sids['phone'], additional_ids) profile = await id_lookup(source_sids['phone']) logger.debug('new profile', profile) if source_sids.get('tg'): await bot_chat_event(sid_chat=source_sids['tg'], name='fblogin', data=me) return response.redirect(cfg.urls.alena_success.url)