def create_post(user, sync=False, **kw): """ Creates a proper platform Post given a user and post components. Special args: sync - <bool:default=False> forces synchronous postprocessing skip_acl_check - <bool:default=False> creates post w/o checking acl permissions on parent channel (e.g. bots) """ """ Creates a proper platform Post given a user and post components. Special args: sync - <bool:default=False> forces synchronous postprocessing """ # Set user in thread local storage from solariat_bottle.db.user import set_user set_user(user) from solariat_bottle.db.post.utils import get_platform_class from solariat_bottle.utils.post import get_language from solariat_bottle.db.channel.base import Channel from solariat_bottle.utils.posts_tracking import log_state, PostState, get_post_natural_id log_state(kw.get('channel', kw.get('channels', None)), get_post_natural_id(kw), PostState.DELIVERED_TO_TANGO) post_lang = get_language(kw) if post_lang.support_level == Support.NO: logger.info("Detect message for unsupported language: %s" % post_lang.lang) logger.info("Unsupported message value is: %s" % str(kw)) return else: kw['lang'] = post_lang kw = normalize_post_params(user, kw) klass = get_platform_class(kw['_platform'], event_type=kw['event_type']) # we have channels resolved in normalize_post_params channels = kw['channels'] accounts = set([ch.account for ch in channels]) for account in accounts: if _check_account_volume(user, account): msg = u"Account '{} ({})' has reached its monthly volume threshold.".format( account.name, account.id) LOGGER.warning(msg) if _check_account_daily_volume(user, account): msg = u"Account '{} ({})' has reached its daily volume threshold.".format( account.name, account.id) LOGGER.warning(msg) return klass.objects.create_by_user(user, safe_create=True, sync=sync, **kw)
def create_by_user(self, user, **kw): post_lang = get_language(kw) kw['lang'] = post_lang if 'content' not in kw: kw['content'] = 'No verbatim provided' assert kw.get('case_number'), kw kw['is_inbound'] = True kw['safe_create'] = True # We need to override posts for NPS, # so we need to check if post exist, # if post exist let remove it and re-create if kw.get('actor_id'): CustomerProfile = user.account.get_customer_profile_class() actor_num = CustomerProfile.objects.get( kw.get('actor_id')).actor_num elif kw.get('user_profile'): # TODO: [gsejop] create anonymous CustomerProfile? # actor_num = kw['user_profile'].customer_profile.actor_num actor_num = kw['user_profile'].actor_num else: actor_num = 0 if kw['user_profile']: kw['profile_data'] = kw['user_profile'].data nps_event_id = pack_event_id(actor_num, kw['_created']) try: nps_post = self.get(id=nps_event_id) raise Exception('NPSOutcome with nps_event_id: %s exists already' % nps_event_id) except NPSOutcome.DoesNotExist: pass try: nps_post = NPSOutcome.get_by_native_id(kw['native_id']) raise Exception('NPSOutcome with native_id: %s exists already' % kw['native_id']) except NPSOutcome.DoesNotExist: pass normalize_post_params(user, kw) post = super(NPSOutcomeManager, self).create_by_user(user, **kw) # self._postprocess_new_post(user, post, sync) # _set_channel_and_tag_assignments(post) # post.compute_journey_information() # why we needed this? PostManager.create_by_user already did this return post
def test_unicode(self): post_dict = dict(content=u'\u0938\u0941\u091c\u0928') lang = get_language(post_dict) self.assertIn(lang.lang, ['ja', 'hi'])
def test_invalid_utf(self): post_dict = dict(content="\xc3\x28") lang = get_language(post_dict) self.assertEqual(lang.lang, 'en')
def test_invalid_text(self): post_dict = dict(content='$$$') lang = get_language(post_dict) self.assertEqual(lang.lang, 'en')
def lookup_tracked_channels(platform_name, post, keywords=None, logger=LOGGER): from solariat_bottle.db.channel.base import Channel from solariat_bottle.db.channel.twitter import get_sync_usernames_list, \ KeywordTrackingChannel from solariat_bottle.db.tracking import PostFilterEntry, \ PostFilterEntryPassive, PostFilterStream, get_filter_type_id from solariat_bottle.utils.post import get_language, is_retweet, \ get_service_channel_memoized F = PostFilterEntry.F normalize = TrackingNLP.normalize_kwd post['lang'] = get_language(post) lang_code = post['lang'].lang if keywords is None: keywords = TrackingNLP.extract_all(post) def safe_channels(filter_channel_map): channel_id_filter_map = defaultdict(set) for filter_id, (filter_type, channel_refs) in filter_channel_map.iteritems(): for ref in channel_refs: channel_id_filter_map[ref.id].add((filter_id, filter_type)) expected_channel_ids = channel_id_filter_map.keys() channels = list( Channel.objects.coll.find({ Channel.F.id: { "$in": expected_channel_ids }, Channel.F.status: { "$in": ['Active', 'Interim'] } })) channels = map(Channel, channels) active_channel_ids = set(ch.id for ch in channels) missing_channels = set(expected_channel_ids) - active_channel_ids if missing_channels: from solariat.db.abstract import DBRef models = {ACTIVE: PostFilterEntry, PASSIVE: PostFilterEntryPassive} for channel_id in missing_channels: channel_ref = DBRef('Channel', channel_id) for filter_id, filter_type in channel_id_filter_map[ channel_id]: model = models[filter_type] logger.warning("Channel pulled from %s(%s): %s" % (model.__name__, filter_id, channel_id)) model.objects.coll.update( {"_id": filter_id}, {"$pull": { model.F('channels'): channel_ref }}) PostFilterStream.refresh_stats() PostFilterEntry.objects.remove(channels=[]) return channels filter_channel_refs_map = {} ACTIVE = 0 PASSIVE = 1 post_filter_query = { F.entry: { "$in": keywords }, F.filter_type_id: get_filter_type_id('KEYWORD') } if lang_code in LANG_CODES: post_filter_query[F.lang] = lang_code for item in PostFilterEntry.objects.coll.find(post_filter_query, fields={F.channels: True}): filter_channel_refs_map[item['_id']] = (ACTIVE, item[F.channels]) sender_user_ids, sender_user_screen_names, recipient_user_screen_names = get_twitter_post_users( post) user_screen_names = get_sync_usernames_list( [name.lower() for name in set(sender_user_screen_names)]) recipient_user_screen_names = get_sync_usernames_list( [name.lower() for name in set(recipient_user_screen_names)]) if recipient_user_screen_names: # lookup recipients among keywords for item in PostFilterEntry.objects.coll.find( { F.entry: { "$in": recipient_user_screen_names }, F.filter_type_id: get_filter_type_id('KEYWORD') }, fields={F.channels: True}): filter_channel_refs_map[item['_id']] = (ACTIVE, item[F.channels]) if user_screen_names: # lookup senders among tracked screen names for item in PostFilterEntry.objects.coll.find( { F.entry: { "$in": user_screen_names }, F.filter_type_id: get_filter_type_id('USER_NAME') }, fields={F.channels: True}): filter_channel_refs_map[item['_id']] = (ACTIVE, item[F.channels]) if sender_user_ids: # lookup senders among tracked user ids for item in PostFilterEntry.objects.coll.find({ F.entry: { "$in": sender_user_ids }, F.filter_type_id: get_filter_type_id('USER_ID') }): filter_channel_refs_map[item['_id']] = (ACTIVE, item[F.channels]) for item in PostFilterEntryPassive.objects.coll.find( {F.entry: { "$in": sender_user_ids }}): filter_channel_refs_map[item['_id']] = (PASSIVE, item[F.channels]) channels = safe_channels(filter_channel_refs_map) # for channel in list(channels): # if isinstance(channel, KeywordTrackingChannel) and \ # set(map(normalize, channel.skipwords)).intersection(set( # LingualToken.extend_langifyed(keywords, lang=lang_code))): # channels.remove(channel) if platform_name == 'Twitter' and is_retweet(post): service_channel_map = { c: get_service_channel_memoized(c) for c in channels } for channel, sc in service_channel_map.iteritems(): if sc: try: sc.reload() except Channel.DoesNotExist: channels.remove(channel) continue if sc and sc.skip_retweets is True: logger.debug('skipping retweet "%s" for channel %s' % (post['content'], channel)) channels.remove(channel) # For direct messages, also make sure that all the channels actually have access to it if post.pop('direct_message', False): logger.debug('extra-filtering channels for a direct message') sender_handle = post.pop('sender_handle', False) recipient_handle = post.pop('recipient_handle', False) if not (sender_handle and recipient_handle): # We don't have a handle so we don't know who this is adressed to. # Just return empty list. logger.warning( "Need a sender and reciever handle in order to process direct messages, but got none." ) return [] channels = [ c for c in channels if (get_service_channel_memoized(c) and c.has_private_access(sender_handle, recipient_handle)) ] tracked_channels = [c for c in channels if c.platform == platform_name] # if app_mode == 'test': # try: # LOGGER.debug(u'channels for post %s\n%s' % (u'%s %s' % (post['content'], post['user_profile']['user_name']), # '\n'.join(u"%s[%s]" % (ch.title, ch) for ch in tracked_channels))) # except: # pass return tracked_channels