Ejemplo n.º 1
0
    def get(self):
        data = self._build_search_form_data()
        form = search_base.SearchForm(data=data)

        if not form.validate():
            for field, errors in form.errors.items():
                for error in errors:
                    self.add_error(u"%s error: %s" %
                                   (getattr(form, field).label.text, error))

        geocode = None
        distance = None
        if form.location.data:
            try:
                geocode, distance = search_base.get_geocode_with_distance(form)
            except:
                self.add_error('Could not geocode location')

        if self.has_errors():
            if self.version == (1, 0):
                self.write_json_success({'results': []})
                return
            else:
                self.errors_are_fatal()

        search_results = []
        form.distance.data = 50
        form.distance_units.data = 'km'
        search_query = form.build_query()
        searcher = search.Search(search_query, deb=form.deb.data)
        need_full_event = self.version < (2, 0)
        # TODO(lambert): Increase the size limit when our clients can handle it. And improve our result sorting to return the 'best' results.
        searcher.limit = 500 if need_full_event else 1000
        search_results = searcher.get_search_results(
            full_event=need_full_event)

        logging.info("Found %s keyword=%r events within %s %s of %s",
                     len(search_results), form.keywords.data,
                     form.distance.data, form.distance_units.data,
                     form.location.data)

        # Keep in sync with mobile react code? And search_servlets
        skip_people = len(search_results) >= 10 or form.skip_people.data
        json_response = api_format.build_search_results_api(
            form,
            search_query,
            search_results,
            self.version,
            need_full_event,
            geocode,
            distance,
            skip_people=skip_people)
        if self.request.get('client') == 'react-android' and self.version <= (
                1, 3):
            json_response['featured'] = []
        self.write_json_success(json_response)
Ejemplo n.º 2
0
def prepare_event_notifications(days, min_attendees, min_dancers,
                                allow_reposting):
    today = datetime.date.today()
    query = search_base.SearchQuery()
    query.start_date = today + datetime.timedelta(days=days)
    query.end_date = today + datetime.timedelta(days=days)
    query.min_attendees = min_attendees
    searcher = search.Search(query)
    results = searcher.get_search_results()
    for result in results:
        pubsub.eventually_publish_event(result.event_id,
                                        post_type=pubsub.POST_TYPE_REMINDER,
                                        min_attendees=min_attendees,
                                        min_dancers=min_dancers,
                                        allow_reposting=allow_reposting)
Ejemplo n.º 3
0
def _generate_results_for(city, week_start):
    start_time = week_start
    end_time = start_time + datetime.timedelta(days=8)

    latlng_bounds = ((city.latitude, city.longitude), (city.latitude,
                                                       city.longitude))
    city_bounds = math.expand_bounds(latlng_bounds,
                                     cities_db.NEARBY_DISTANCE_KM)
    search_query = search_base.SearchQuery(
        time_period=search_base.TIME_ALL_FUTURE,
        start_date=start_time,
        end_date=end_time,
        bounds=city_bounds)
    searcher = search.Search(search_query)
    search_results = searcher.get_search_results(full_event=True)
    return search_results
def promote_events_to_user(user):
    # TODO: Adjust when we have iphone notifications
    if not android.can_notify(user):
        return

    logging.info("Promoting new events to user %s", user.fb_uid)
    # Only send notifications for Mike for now
    user = users.User.get_by_id(user.fb_uid)
    if not user:
        logging.error("No user found: %s", user.fb_uid)
        return
    if user.expired_oauth_token:
        logging.info("User has expired token, aborting: %s", user.fb_uid)
        return

    user_location = user.location
    if not user_location:
        return
    distance_in_km = user.distance_in_km()
    min_attendees = user.min_attendees

    # search for relevant events
    geocode = gmaps_api.lookup_address(user_location)
    if not geocode:
        return None
    bounds = math.expand_bounds(geocode.latlng_bounds(), distance_in_km)
    query = search_base.SearchQuery(time_period=search_base.TIME_UPCOMING, bounds=bounds, min_attendees=min_attendees)

    one_day_ago = time.mktime((datetime.datetime.now() - datetime.timedelta(hours=24)).timetuple())

    search_query = search.Search(query)
    search_query.extra_fields = ['creation_time']
    search_results = search_query._get_candidate_doc_events()
    # TODO: can we move this filter into the search query itself??
    recent_events = [x.doc_id for x in search_results if x.field('creation_time').value > one_day_ago]

    logging.info("Found %s search_results, %s new events", len(search_results), len(recent_events))
    for event_id in recent_events:
        if android.add_notify(user, event_id):
            logging.info("Sent notification!")
Ejemplo n.º 5
0
    def get(self):
        self.finish_preload()
        form = search_base.SearchForm(
            formdata=self.request.GET,
            data=self.user.dict_for_form() if self.user else None)
        if not form.validate():
            logging.warning("Form errors: %s", form.errors)
            self.write_json_response([])
            return
        search_query = form.build_query(start_end_query=True)
        search_results = search.Search(search_query).get_search_results()

        if 'class' in form.deb.data:
            from dancedeets.classes import class_index
            class_results = class_index.ClassSearch(
                search_query).get_search_results()
            search_results += class_results
            search_results.sort(key=lambda x: x.start_time)

        json_results = []
        for result in search_results:
            start_time = result.start_time
            end_time = result.fake_end_time
            duration = end_time - start_time
            if duration > datetime.timedelta(days=5):
                end_time = start_time
            elif duration <= datetime.timedelta(days=1):
                end_time = start_time
            all_day = False
            title = '@ %s\n\n%s' % (result.actual_city_name, result.name)
            json_results.append(
                dict(
                    id=result.event_id,
                    title=title,
                    start=start_time.strftime('%Y-%m-%dT%H:%M:%SZ'),
                    end=end_time.strftime('%Y-%m-%dT%H:%M:%SZ'),
                    url=urls.dd_event_url(result.event_id),
                    allDay=all_day,
                ))
        self.write_json_response(json_results)
    def get(self, name):
        topics = topic_db.Topic.query(topic_db.Topic.url_path == name).fetch(1)
        if not topics:
            self.response.set_status(404)
            return

        topic = topics[0]
        topic.init()

        def prefilter(doc_event):
            """Function for fitlering doc results, before we spend the energy to load the corresponding DBEvents.

            We only want on-topic events here:
            - Must contain keyword in the title
            - Must contain keyword on a line where it makes up >10% of the text (for judges, workshops, etc). We want to hide the resume-includes-classes-from-X people
            """
            logging.info("Prefiltering event %s", doc_event.doc_id)
            name = doc_event.field('name').value.lower()
            description = doc_event.field('description').value.lower()

            description_lines = description.split('\n')

            for keyword in topic.search_keywords:
                keyword_word_re = re.compile(r'\b%s\b' % keyword)
                if keyword_word_re.search(name):
                    return True
                for line in description_lines:
                    result = keyword_word_re.search(line)
                    # If the keyword is more than 10% of the text in the line:
                    # Examples:
                    #   "- HOUSE - KAPELA (Serial Stepperz/Wanted Posse)"
                    #   "5th November : EVENT Judged by HIRO :"
                    if result:
                        if 1.0 * len(keyword) / len(line) > 0.1:
                            return True
                        else:
                            logging.info(
                                "Found keyword %r on line, but not long enough: %r",
                                keyword, line)

            logging.info("Prefilter dropping event %s with name: %r" %
                         (doc_event.doc_id, name))
            return False

        keywords = ' OR '.join('"%s"' % x for x in topic.search_keywords)
        search_query = search_base.SearchQuery(keywords=keywords)
        # Need these fields for the prefilter
        search_query.extra_fields = ['name', 'description']
        # TODO: query needs to include the 'all time' bits somehow, so we can grab all events for our topic pages
        searcher = search.Search(search_query)
        searcher.search_index = search.AllEventsIndex
        search_results = searcher.get_search_results(prefilter=prefilter)

        json_search_response = api_format.build_search_results_api(
            None,
            search_query,
            search_results, (2, 0),
            need_full_event=False,
            geocode=None,
            distance=None)

        videos = get_videos_for(topic.youtube_query)

        if topic.social().get('instagram'):
            instagrams = get_instagrams_for(topic.social()['instagram'])
        else:
            instagrams = {'items': []}

        topic_json = {
            'title': topic.title(),
            'description': topic.description(),
            'image_url': topic.image_url(),
            'social': topic.social(),
        }

        props = dict(
            response=json_search_response,
            videos=videos,
            instagrams=instagrams,
            topic=topic_json,
        )

        self.setup_react_template('topic.js', props)
        self.render_template('topic')