예제 #1
0
    def get(self, username):
        """
        Render a user page.
        """
        publicuser = UserPrefs.all().filter('name =', username).get()

        if not publicuser:
            self.abort(404)

        recipes = Recipe.all()\
                        .filter('owner =', publicuser)\
                        .order('name')\
                        .run(limit=25)

        actions = UserAction.all()\
                            .filter('owner =', publicuser)\
                            .order('-created')\
                            .fetch(15)

        object_ids = UserAction.gather_object_ids(actions)

        user_map = {publicuser.key().id(): publicuser}

        for user in UserPrefs.get_by_id(object_ids['users']):
            user_map[user.key().id()] = user

        recipes = [r for r in recipes]
        recipe_ids = [recipe.key().id() for recipe in recipes]
        object_ids['recipes'] = [
            id for id in object_ids['recipes'] if id not in recipe_ids
        ]

        recipe_map = {}

        for recipe in recipes:
            recipe.owner = publicuser
            recipe_map[recipe.key().id()] = recipe

        for recipe in Recipe.get_by_id(object_ids['recipes']):
            recipe_map[recipe.key().id()] = recipe

        brew_map = {}

        for brew in Brew.get_by_id(object_ids['brews']):
            brew_map[brew.key().id()] = brew

        self.render(
            'user.html', {
                'publicuser': publicuser,
                'recipes': recipes,
                'actions': actions,
                'user_map': user_map,
                'recipe_map': recipe_map,
                'brew_map': brew_map
            })
예제 #2
0
    def get(self, username):
        """
        Render a user page.
        """
        publicuser = UserPrefs.all().filter('name =', username).get()

        if not publicuser:
            self.abort(404)

        recipes = Recipe.all()\
                        .filter('owner =', publicuser)\
                        .order('name')\
                        .run(limit=25)

        actions = UserAction.all()\
                            .filter('owner =', publicuser)\
                            .order('-created')\
                            .fetch(15)

        object_ids = UserAction.gather_object_ids(actions)

        user_map = {
            publicuser.key().id(): publicuser
        }

        for user in UserPrefs.get_by_id(object_ids['users']):
            user_map[user.key().id()] = user

        recipes = [r for r in recipes]
        recipe_ids = [recipe.key().id() for recipe in recipes]
        object_ids['recipes'] = [id for id in object_ids['recipes'] if id not in recipe_ids]

        recipe_map = {}

        for recipe in recipes:
            recipe.owner = publicuser
            recipe_map[recipe.key().id()] = recipe

        for recipe in Recipe.get_by_id(object_ids['recipes']):
            recipe_map[recipe.key().id()] = recipe

        brew_map = {}

        for brew in Brew.get_by_id(object_ids['brews']):
            brew_map[brew.key().id()] = brew

        self.render('user.html', {
            'publicuser': publicuser,
            'recipes': recipes,
            'actions': actions,
            'user_map': user_map,
            'recipe_map': recipe_map,
            'brew_map': brew_map
        })
예제 #3
0
파일: users.py 프로젝트: jensyt/malt.io
    def process(self, username, action):
        """
        Follow the given user.
        """
        user = UserPrefs.get()
        publicuser = UserPrefs.all().filter('name =', username).get()

        if not user or not publicuser:
            return self.render_json({
                'status': 'error',
                'error': 'User not found'
            })

        if action == 'post':
            if publicuser.user_id in user.following:
                return self.render_json({
                    'status': 'error',
                    'error': 'Already following user'
                })

            user.following.append(publicuser.user_id)

            existing = UserAction.all()\
                                 .filter('owner =', user)\
                                 .filter('type =', UserAction.TYPE_USER_FOLLOWED)\
                                 .filter('object_id =', publicuser.key().id())\
                                 .count()

            if not existing:
                user_action = UserAction()
                user_action.owner = user
                user_action.type = user_action.TYPE_USER_FOLLOWED
                user_action.object_id = publicuser.key().id()
                user_action.put()
        else:
            if publicuser.user_id not in user.following:
                return self.render_json({
                    'status': 'error',
                    'error': 'User not being followed'
                })

            user.following.remove(publicuser.user_id)

            existing = UserAction.all()\
                                 .filter('owner =', user)\
                                 .filter('type =', UserAction.TYPE_USER_FOLLOWED)\
                                 .filter('object_id =', publicuser.key().id())\
                                 .get()

            if existing:
                existing.delete()

        # Save updated following list
        user.put()

        self.render_json({
            'status': 'ok'
        })
예제 #4
0
    def process(self, action, username=None, recipe_slug=None):
        """
        Process a request to add or remove a user from the liked list.
        """
        user = UserPrefs.get()
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({'status': 'error', 'error': 'User not found'})
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({'status': 'error', 'error': 'Recipe not found'})
            return

        if action == 'post':
            if user.user_id not in recipe.likes:
                recipe.likes.append(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .count()

                if not existing:
                    user_action = UserAction()
                    user_action.owner = user
                    user_action.type = user_action.TYPE_RECIPE_LIKED
                    user_action.object_id = recipe.key().id()
                    user_action.put()

        elif action == 'delete':
            if user.user_id in recipe.likes:
                recipe.likes.remove(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .get()

                if existing:
                    existing.delete()

        return self.render_json({'status': 'ok', 'likes': len(recipe.likes)})
예제 #5
0
    def process(self, username, action):
        """
        Follow the given user.
        """
        user = self.user
        publicuser = UserPrefs.all().filter('name =', username).get()

        if not user or not publicuser:
            return self.render_json({
                'status': 'error',
                'error': 'User not found'
            })

        if action == 'post':
            if publicuser.user_id in user.following:
                return self.render_json({
                    'status': 'error',
                    'error': 'Already following user'
                })

            user.following.append(publicuser.user_id)

            existing = UserAction.all()\
                                 .filter('owner =', user)\
                                 .filter('type =', UserAction.TYPE_USER_FOLLOWED)\
                                 .filter('object_id =', publicuser.key().id())\
                                 .count()

            if not existing:
                user_action = UserAction()
                user_action.owner = user
                user_action.type = user_action.TYPE_USER_FOLLOWED
                user_action.object_id = publicuser.key().id()
                user_action.put()
        else:
            if publicuser.user_id not in user.following:
                return self.render_json({
                    'status': 'error',
                    'error': 'User not being followed'
                })

            user.following.remove(publicuser.user_id)

            existing = UserAction.all()\
                                 .filter('owner =', user)\
                                 .filter('type =', UserAction.TYPE_USER_FOLLOWED)\
                                 .filter('object_id =', publicuser.key().id())\
                                 .get()

            if existing:
                existing.delete()

        # Save updated following list
        user.put()

        self.render_json({
            'status': 'ok'
        })
예제 #6
0
파일: donate.py 프로젝트: pheezer/malt.io
    def post(self):
        """
        Process a donation payment given a Stripe single-use token.
        """
        user = self.user
        stripe.api_key = settings.STRIPE_PRIVATE_KEY

        amount = int(cgi.escape(self.request.get('amount')))
        token = cgi.escape(self.request.get('stripeToken'))

        # Charge the amount (in cents) to the customer's card
        charge = stripe.Charge.create(**{
            'amount': amount * 100,
            'currency': 'usd',
            'card': token,
            'description': 'Donation from ' + (user and user.name or 'Anonymous')
        })

        if user:
            # Add an award to this user for donating
            if user and 'donated' not in user.awards:
                user.awards.append('donated')
                user.put()

            # Log action
            action = UserAction()
            action.owner = user
            action.type = action.TYPE_USER_DONATED
            action.put()

        self.redirect('/donate?success=true')
예제 #7
0
    def top_interesting_events(self):
        """
        Get a list of interesting events ordered by date from most
        recent to least. Interesting events are events that either belong
        to this user or any user she is following.
        """
        from models.useraction import UserAction

        following = self.following_users.run(batch_size=100)

        return UserAction.all()\
                         .filter('owner IN', [self] + list(following))\
                         .order('-created')\
                         .fetch(25)
예제 #8
0
파일: recipes.py 프로젝트: jensyt/malt.io
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        new_recipe = Recipe(**{
            'owner': UserPrefs.get(),
            'cloned_from': recipe,
            'color': recipe.color,
            'ibu': recipe.ibu,
            'alcohol': recipe.alcohol,
            'name': recipe.name,
            'description': recipe.description,
            'type': recipe.type,
            'style': recipe.style,
            'batch_size': recipe.batch_size,
            'boil_size': recipe.boil_size,
            'bottling_temp': recipe.bottling_temp,
            'bottling_pressure': recipe.bottling_pressure,
            '_ingredients': recipe._ingredients
        })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()

        action = UserAction()
        action.owner = UserPrefs.get()
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({
            'status': 'ok',
            'redirect': new_recipe.url
        })
예제 #9
0
    def delete(self, username=None, recipe_slug=None):
        """
        Handle recipe delete. This will remove a recipe and return success
        or failure.
        """
        user = self.user

        if not user:
            self.render_json({
                'status': 'error',
                'error': 'User not logged in'
            })

        recipe = Recipe.all()\
                       .filter('slug = ', recipe_slug)\
                       .filter('owner =', user)\
                       .get()

        if recipe:
            # Delete all actions pointing to this recipe
            actions = UserAction.all()\
                                .filter('type IN', [UserAction.TYPE_RECIPE_CREATED,
                                                    UserAction.TYPE_RECIPE_EDITED,
                                                    UserAction.TYPE_RECIPE_CLONED,
                                                    UserAction.TYPE_RECIPE_LIKED])\
                                .filter('object_id =', recipe.key().id())\
                                .fetch(1000)

            for action in actions:
                action.delete()

            # Delete the actual recipe itself
            recipe.delete()

            self.render_json({
                'status': 'ok',
                'redirect': '/users/%(username)s/recipes' % {
                    'username': user.name
                }
            })
        else:
            self.render_json({
                'status': 'error',
                'error': 'Unable to delete recipe'
            })
예제 #10
0
파일: recipes.py 프로젝트: pheezer/malt.io
    def delete(self, username=None, recipe_slug=None):
        """
        Handle recipe delete. This will remove a recipe and return success
        or failure.
        """
        user = self.user

        if not user:
            self.render_json({
                'status': 'error',
                'error': 'User not logged in'
            })

        recipe = Recipe.all()\
                       .filter('slug = ', recipe_slug)\
                       .filter('owner =', user)\
                       .get()

        if recipe:
            # Delete all actions pointing to this recipe
            actions = UserAction.all()\
                                .filter('type IN', [UserAction.TYPE_RECIPE_CREATED,
                                                    UserAction.TYPE_RECIPE_EDITED,
                                                    UserAction.TYPE_RECIPE_CLONED,
                                                    UserAction.TYPE_RECIPE_LIKED])\
                                .filter('object_id =', recipe.key().id())\
                                .fetch(1000)

            for action in actions:
                action.delete()

            # Delete the actual recipe itself
            recipe.delete()

            self.render_json({
                'status': 'ok',
                'redirect': '/users/%(username)s/recipes' % {
                    'username': user.name
                }
            })
        else:
            self.render_json({
                'status': 'error',
                'error': 'Unable to delete recipe'
            })
예제 #11
0
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({'status': 'error', 'error': 'User not found'})
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({'status': 'error', 'error': 'Recipe not found'})
            return

        new_recipe = Recipe(
            **{
                'owner': UserPrefs.get(),
                'cloned_from': recipe,
                'color': recipe.color,
                'ibu': recipe.ibu,
                'alcohol': recipe.alcohol,
                'name': recipe.name,
                'description': recipe.description,
                'type': recipe.type,
                'style': recipe.style,
                'batch_size': recipe.batch_size,
                'boil_size': recipe.boil_size,
                'bottling_temp': recipe.bottling_temp,
                'bottling_pressure': recipe.bottling_pressure,
                '_ingredients': recipe._ingredients
            })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()

        action = UserAction()
        action.owner = UserPrefs.get()
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({'status': 'ok', 'redirect': new_recipe.url})
예제 #12
0
파일: recipes.py 프로젝트: pheezer/malt.io
    def post(self):
        """
        Import a new recipe or list of recipes from BeerXML to the
        currently logged in user's account.
        """
        user = self.user
        recipesxml = self.request.POST['file'].value

        for recipe in Recipe.new_from_beerxml(recipesxml):
            recipe.owner = user
            recipe.slug = generate_usable_slug(recipe)
            recipe.update_cache()
            key = recipe.put()

            action = UserAction()
            action.owner = user
            action.object_id = key.id()
            action.type = action.TYPE_RECIPE_CREATED
            action.put()

        self.redirect('/users/' + user.name + '/recipes')
예제 #13
0
    def post(self):
        """
        Import a new recipe or list of recipes from BeerXML to the
        currently logged in user's account.
        """
        user = self.user
        recipesxml = self.request.POST['file'].value

        for recipe in Recipe.new_from_beerxml(recipesxml):
            recipe.owner = user
            recipe.slug = generate_usable_slug(recipe)
            recipe.update_cache();
            key = recipe.put()

            action = UserAction()
            action.owner = user
            action.object_id = key.id()
            action.type = action.TYPE_RECIPE_CREATED
            action.put()

        self.redirect('/users/' + user.name + '/recipes')
예제 #14
0
    def create_or_update(auth_id, user_info, auth_info):
        """
        Create a new user or update an existing one with information such
        as id, name, email, avatar, etc.
        """
        prefs = UserPrefs.all()\
                         .filter('user_id =', auth_id)\
                         .get()

        # Backwards compatibility
        if not prefs:
            prefs = UserPrefs.all()\
                             .filter('email =', user_info['email'])\
                             .get()

            if prefs:
                if ':' not in prefs.user_id:
                    # Old-style user and the emails match, so update!
                    prefs.user_id = auth_id
                else:
                    # New-style user, ignore
                    prefs = None

        # Not found yet... time to create a new one!
        if not prefs:
            # Generate a nice username from the email
            username = user_info['email'].split('@')[0].lower().replace(' ', '')
            count = 0

            while True:
                check_name = count and username + str(count) or username
                if not UserPrefs.all()\
                                .filter('name =', check_name)\
                                .count() and check_name not in settings.RESERVED_USERNAMES:
                    if count:
                        username = username + str(count)
                    break

                count += 1

            # Create the preferences object and store it
            prefs = UserPrefs(**{
                'user_id': auth_id,
                'name': username,
                'joined': Date().date,
            })

            # Write to the db so this user object gets a proper id, which
            # is required to reference it in the action created below
            prefs.put()

            from models.useraction import UserAction

            action = UserAction()
            action.owner = prefs
            action.type = action.TYPE_USER_JOINED
            action.put()

            # Invalidate cached user list pages
            memcache.delete('users-content')

        # Update fields based on latest user info
        prefs.email = user_info['email']

        # Update the avatar, except for special users
        if prefs.name not in ['examples']:
            prefs.avatar = user_info['avatar']

        prefs.put()

        return prefs
예제 #15
0
파일: index.py 프로젝트: jensyt/malt.io
    def get(self):
        """
        Render the index page. Currently this renders a 'Coming soon' landing
        page that will eventually be replaced with a proper home page.
        """
        user = self.user

        if user:
            # Try to get rendered output from memcache
            rendered = memcache.get('dashboard-' + user.user_id)
            if rendered and not settings.DEBUG:
                return self.response.out.write(rendered)

            # Fetch following users
            following = user.following_users\
                            .order('name')\
                            .fetch(100)

            user_keys = [user.key()] + [u.key() for u in following]

            # Start async fetch of top recipes
            top_recipes = Recipe.all()\
                                .filter('owner IN', user_keys)\
                                .order('-likes_count')\
                                .run(limit=15)

            # Get and process interesting events
            interesting_events = UserAction.all()\
                                           .filter('owner IN', user_keys)\
                                           .order('-created')\
                                           .fetch(15)

            object_ids = UserAction.gather_object_ids(interesting_events)
            object_ids['users'] = [id for id in object_ids['users'] if id not in [user.key().id()] + user.following]

            # Start async fetch of relevant recipes
            recipes = db.get_async([Key.from_path('Recipe', id) for id in object_ids['recipes']])

            # Convert iterators to  lists of items in memory and setup a map
            # of user id -> user for easy lookups
            following = list(following)
            top_recipes = list(top_recipes)

            user_map = {
                user.key().id(): user
            }

            for u in following:
                user_map[u.key().id()] = u

            if object_ids['users']:
                for u in UserPrefs.get_by_id(object_ids['users']):
                    user_map[u.key().id()] = u

            # Setup a map of recipe id -> recipe for easy lookups
            recipe_map = {}

            for r in recipes.get_result():
                recipe_map[r.key().id()] = r

            # Render and cache for 1 minute
            memcache.set('dashboard-' + user.user_id, self.render('dashboard.html', {
                'following': following,
                'user_map': user_map,
                'recipe_map': recipe_map,
                'top_recipes': top_recipes,
                'interesting_events': interesting_events
            }), 60)
        else:
            # Try to get rendered output from memcache
            rendered = memcache.get('index')
            if rendered and not settings.DEBUG:
                return self.response.out.write(rendered)

            recipes = Recipe.all()\
                            .order('-likes_count')\
                            .run(limit=15)

            # Render and cache for 15 minutes
            memcache.set('index', self.render('index.html', {
                'recipes': recipes
            }), 900)
예제 #16
0
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        new_recipe = Recipe(**{
            'owner': self.user,
            'cloned_from': recipe,
            'color': recipe.color,
            'ibu': recipe.ibu,
            'alcohol': recipe.alcohol,
            'name': recipe.name,
            'description': recipe.description,
            'type': recipe.type,
            'category': recipe.category,
            'style': recipe.style,
            'batch_size': recipe.batch_size,
            'boil_size': recipe.boil_size,
            'bottling_temp': recipe.bottling_temp,
            'bottling_pressure': recipe.bottling_pressure,
            'steep_efficiency': recipe.steep_efficiency,
            'mash_efficiency': recipe.mash_efficiency,
            'primary_days': recipe.primary_days,
            'primary_temp': recipe.primary_temp,
            'secondary_days': recipe.secondary_days,
            'secondary_temp': recipe.secondary_temp,
            'tertiary_days': recipe.tertiary_days,
            'tertiary_temp': recipe.tertiary_temp,
            'aging_days': recipe.aging_days,
            '_ingredients': recipe._ingredients
        })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()
        new_recipe.update_grade()
        new_recipe.put()

        # Update recipe ranking for sorting
        recipe.update_grade()
        recipe.put()

        action = UserAction()
        action.owner = self.user
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({
            'status': 'ok',
            'redirect': new_recipe.url
        })
예제 #17
0
파일: recipes.py 프로젝트: jensyt/malt.io
    def process(self, action, username=None, recipe_slug=None):
        """
        Process a request to add or remove a user from the liked list.
        """
        user = UserPrefs.get()
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        if action == 'post':
            if user.user_id not in recipe.likes:
                recipe.likes.append(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .count()

                if not existing:
                    user_action = UserAction()
                    user_action.owner = user
                    user_action.type = user_action.TYPE_RECIPE_LIKED
                    user_action.object_id = recipe.key().id()
                    user_action.put()

        elif action == 'delete':
            if user.user_id in recipe.likes:
                recipe.likes.remove(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .get()

                if existing:
                    existing.delete()

        return self.render_json({
            'status': 'ok',
            'likes': len(recipe.likes)
        })
예제 #18
0
파일: index.py 프로젝트: pheezer/malt.io
    def get(self):
        user = self.user

        # Try to get rendered output from memcache
        rendered = memcache.get('dashboard-' + user.user_id)
        if rendered and not settings.DEBUG:
            return self.response.out.write(rendered)

        # Fetch following users
        following = user.following_users\
                        .order('name')\
                        .fetch(100)

        user_keys = [user.key()] + [u.key() for u in following]

        # Start async fetch of top recipes
        top_recipes = Recipe.all()\
                            .filter('owner IN', user_keys)\
                            .order('-grade')\
                            .run(limit=15)

        # Get and process interesting events
        interesting_events = UserAction.all()\
                                       .filter('owner IN', user_keys)\
                                       .order('-created')\
                                       .fetch(15)

        object_ids = UserAction.gather_object_ids(interesting_events)
        object_ids['users'] = [
            id for id in object_ids['users']
            if id not in [user.key().id()] + user.following
        ]

        # Start async fetch of relevant recipes
        recipes = db.get_async(
            [Key.from_path('Recipe', id) for id in object_ids['recipes']])

        # Start async fetch of relevant brews
        brews = db.get_async(
            [Key.from_path('Brew', id) for id in object_ids['brews']])

        # Convert iterators to  lists of items in memory and setup a map
        # of user id -> user for easy lookups
        following = list(following)
        top_recipes = list(top_recipes)

        user_map = {user.key().id(): user}

        for u in following:
            user_map[u.key().id()] = u

        if object_ids['users']:
            for u in UserPrefs.get_by_id(object_ids['users']):
                user_map[u.key().id()] = u

        # Setup a map of brew id -> brew for easy lookups
        brew_map = {}
        brew_recipe_ids = set()

        for b in brews.get_result():
            brew_recipe_ids.add(b.recipe_key.id())
            brew_map[b.key().id()] = b

        # Async fetch of any recipes brews reference that weren't
        # included in the recipe fetch above...
        brew_recipes = db.get_async([
            Key.from_path('Recipe', id) for id in brew_recipe_ids
            if id not in object_ids['recipes']
        ])

        # Setup a map of recipe id -> recipe for easy lookups
        recipe_map = {}

        for r in recipes.get_result():
            recipe_map[r.key().id()] = r

        for r in brew_recipes.get_result():
            recipe_map[r.key().id()] = r

        # Render and cache for 1 minute
        memcache.set(
            'dashboard-' + user.user_id,
            self.render(
                'dashboard.html', {
                    'following': following,
                    'user_map': user_map,
                    'recipe_map': recipe_map,
                    'brew_map': brew_map,
                    'top_recipes': top_recipes,
                    'interesting_events': interesting_events
                }), self.CACHE_TIME)
예제 #19
0
                key = recipe.put()

                # Save the historic version to database
                historic.put()

                changed = True
        else:
            # Save recipe to database
            key = recipe.put()

        # Update grade now that we have a key
        recipe.update_grade()
        recipe.put()

        if not historic or changed:
            action = UserAction()
            action.owner = user
            action.object_id = key.id()

            if not recipe_slug:
                action.type = action.TYPE_RECIPE_CREATED
            else:
                action.type = action.TYPE_RECIPE_EDITED

            action.put()

        self.render_json({
            'status': 'ok',
            'redirect': '/users/%(username)s/recipes/%(slug)s' % {
                'username': user.name,
                'slug': recipe.slug
예제 #20
0
    def get(self):
        """
        Render the index page. Currently this renders a 'Coming soon' landing
        page that will eventually be replaced with a proper home page.
        """
        user = self.user

        if user:
            # Try to get rendered output from memcache
            rendered = memcache.get('dashboard-' + user.user_id)
            if rendered and not settings.DEBUG:
                return self.response.out.write(rendered)

            # Fetch following users
            following = user.following_users\
                            .order('name')\
                            .fetch(100)

            user_keys = [user.key()] + [u.key() for u in following]

            # Start async fetch of top recipes
            top_recipes = Recipe.all()\
                                .filter('owner IN', user_keys)\
                                .order('-likes_count')\
                                .run(limit=15)

            # Get and process interesting events
            interesting_events = UserAction.all()\
                                           .filter('owner IN', user_keys)\
                                           .order('-created')\
                                           .fetch(15)

            object_ids = UserAction.gather_object_ids(interesting_events)
            object_ids['users'] = [
                id for id in object_ids['users']
                if id not in [user.key().id()] + user.following
            ]

            # Start async fetch of relevant recipes
            recipes = db.get_async(
                [Key.from_path('Recipe', id) for id in object_ids['recipes']])

            # Convert iterators to  lists of items in memory and setup a map
            # of user id -> user for easy lookups
            following = list(following)
            top_recipes = list(top_recipes)

            user_map = {user.key().id(): user}

            for u in following:
                user_map[u.key().id()] = u

            if object_ids['users']:
                for u in UserPrefs.get_by_id(object_ids['users']):
                    user_map[u.key().id()] = u

            # Setup a map of recipe id -> recipe for easy lookups
            recipe_map = {}

            for r in recipes.get_result():
                recipe_map[r.key().id()] = r

            # Render and cache for 1 minute
            memcache.set(
                'dashboard-' + user.user_id,
                self.render(
                    'dashboard.html', {
                        'following': following,
                        'user_map': user_map,
                        'recipe_map': recipe_map,
                        'top_recipes': top_recipes,
                        'interesting_events': interesting_events
                    }), 60)
        else:
            # Try to get rendered output from memcache
            rendered = memcache.get('index')
            if rendered and not settings.DEBUG:
                return self.response.out.write(rendered)

            recipes = Recipe.all()\
                            .order('-likes_count')\
                            .run(limit=15)

            # Render and cache for 15 minutes
            memcache.set('index',
                         self.render('index.html', {'recipes': recipes}), 900)
예제 #21
0
파일: recipes.py 프로젝트: pheezer/malt.io
                key = recipe.put()

                # Save the historic version to database
                historic.put()

                changed = True
        else:
            # Save recipe to database
            key = recipe.put()

        # Update grade now that we have a key
        recipe.update_grade()
        recipe.put()

        if not historic or changed:
            action = UserAction()
            action.owner = user
            action.object_id = key.id()

            if not recipe_slug:
                action.type = action.TYPE_RECIPE_CREATED
            else:
                action.type = action.TYPE_RECIPE_EDITED

            action.put()

        self.render_json({
            'status': 'ok',
            'redirect': '/users/%(username)s/recipes/%(slug)s' % {
                'username': user.name,
                'slug': recipe.slug
예제 #22
0
    def get(self):
        user = self.user

        # Try to get rendered output from memcache
        rendered = memcache.get('dashboard-' + user.user_id)
        if rendered and not settings.DEBUG:
            return self.response.out.write(rendered)

        # Fetch following users
        following = user.following_users\
                        .order('name')\
                        .fetch(100)

        user_keys = [user.key()] + [u.key() for u in following]

        # Start async fetch of top recipes
        top_recipes = Recipe.all()\
                            .filter('owner IN', user_keys)\
                            .order('-grade')\
                            .run(limit=15)

        # Get and process interesting events
        interesting_events = UserAction.all()\
                                       .filter('owner IN', user_keys)\
                                       .order('-created')\
                                       .fetch(15)

        object_ids = UserAction.gather_object_ids(interesting_events)
        object_ids['users'] = [id for id in object_ids['users'] if id not in [user.key().id()] + user.following]

        # Start async fetch of relevant recipes
        recipes = db.get_async([Key.from_path('Recipe', id) for id in object_ids['recipes']])

        # Start async fetch of relevant brews
        brews = db.get_async([Key.from_path('Brew', id) for id in object_ids['brews']])

        # Convert iterators to  lists of items in memory and setup a map
        # of user id -> user for easy lookups
        following = list(following)
        top_recipes = list(top_recipes)

        user_map = {
            user.key().id(): user
        }

        for u in following:
            user_map[u.key().id()] = u

        if object_ids['users']:
            for u in UserPrefs.get_by_id(object_ids['users']):
                user_map[u.key().id()] = u

        # Setup a map of brew id -> brew for easy lookups
        brew_map = {}
        brew_recipe_ids = set()

        for b in brews.get_result():
            brew_recipe_ids.add(b.recipe_key.id())
            brew_map[b.key().id()] = b

        # Async fetch of any recipes brews reference that weren't
        # included in the recipe fetch above...
        brew_recipes = db.get_async([Key.from_path('Recipe', id) for id in brew_recipe_ids if id not in object_ids['recipes']])

        # Setup a map of recipe id -> recipe for easy lookups
        recipe_map = {}

        for r in recipes.get_result():
            recipe_map[r.key().id()] = r

        for r in brew_recipes.get_result():
            recipe_map[r.key().id()] = r

        # Render and cache for 1 minute
        memcache.set('dashboard-' + user.user_id, self.render('dashboard.html', {
            'following': following,
            'user_map': user_map,
            'recipe_map': recipe_map,
            'brew_map': brew_map,
            'top_recipes': top_recipes,
            'interesting_events': interesting_events
        }), self.CACHE_TIME)
예제 #23
0
파일: brew.py 프로젝트: pheezer/malt.io
class BrewHandler(BaseHandler):
    """
        Create a new brew.

        /users/USERNAME/recipes/RECIPE-SLUG/brew
        /users/USERNAME/recipes/RECIPE-SLUG/brew/BREW-SLUG
    """
    def process(self, username=None, recipe_slug=None, brew_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name =', username)\
                              .get()

        if not publicuser:
            return [None, None, None]

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug = ', recipe_slug)\
                       .get()

        if not recipe:
            return [publicuser, None, None]

        if brew_slug is not None:
            brew = Brew.all()\
                       .filter('owner =', publicuser)\
                       .filter('recipe =', recipe)\
                       .filter('slug =', brew_slug)\
                       .get()

            if not brew:
                return [publicuser, recipe, None]
        else:
            brew = Brew()
            brew.owner = self.user
            brew.recipe = recipe

        return [publicuser, recipe, brew]

    def get(self, username=None, recipe_slug=None, brew_slug=None):
        publicuser, recipe, brew = self.process(username, recipe_slug,
                                                brew_slug)

        if not publicuser or not recipe or not brew:
            return self.abort(404)

        self.render('brew.html', {
            'publicuser': publicuser,
            'recipe': recipe,
            'brew': brew
        })

    def post(self, username=None, recipe_slug=None, brew_slug=None):
        publicuser, recipe, brew = self.process(username, recipe_slug,
                                                brew_slug)

        if not publicuser or not recipe or not brew:
            return self.abort(404)

        # Does the current user own this? If not, then fail
        if brew.owner.name != self.user.name:
            return self.abort(403)

        submitted = json.loads(cgi.escape(self.request.get('brew')))

        logging.info(submitted)

        started = submitted['started']
        bottled = submitted['bottled']

        for k, v in [('started', started), ('bottled', bottled)]:
            if v.strip():
                try:
                    d = Date(v, format="%H:%M %d %b %Y")
                except Exception, e:
                    return self.render_json({
                        'status':
                        'error',
                        'error':
                        'Could not process date "%s": %s' % (v, e)
                    })

                setattr(brew, k, d.datetime)

        brew.og = float(submitted['og'])
        brew.fg = float(submitted['fg'])
        brew.rating = submitted['rating']
        brew.notes = submitted['notes']

        brew.slug = generate_usable_slug(brew)
        key = brew.put()

        # Update recipe ranking information for sorting
        recipe.update_grade()
        recipe.put()

        # Add user action
        action = UserAction()
        action.owner = self.user
        action.object_id = key.id()

        if not brew_slug:
            action.type = action.TYPE_BREW_CREATED
        else:
            action.type = action.TYPE_BREW_UPDATED

        action.put()

        self.render_json({'status': 'ok'})
예제 #24
0
파일: recipes.py 프로젝트: pheezer/malt.io
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({'status': 'error', 'error': 'User not found'})
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({'status': 'error', 'error': 'Recipe not found'})
            return

        new_recipe = Recipe(
            **{
                'owner': self.user,
                'cloned_from': recipe,
                'color': recipe.color,
                'ibu': recipe.ibu,
                'alcohol': recipe.alcohol,
                'name': recipe.name,
                'description': recipe.description,
                'type': recipe.type,
                'category': recipe.category,
                'style': recipe.style,
                'batch_size': recipe.batch_size,
                'boil_size': recipe.boil_size,
                'bottling_temp': recipe.bottling_temp,
                'bottling_pressure': recipe.bottling_pressure,
                'steep_efficiency': recipe.steep_efficiency,
                'mash_efficiency': recipe.mash_efficiency,
                'primary_days': recipe.primary_days,
                'primary_temp': recipe.primary_temp,
                'secondary_days': recipe.secondary_days,
                'secondary_temp': recipe.secondary_temp,
                'tertiary_days': recipe.tertiary_days,
                'tertiary_temp': recipe.tertiary_temp,
                'aging_days': recipe.aging_days,
                '_ingredients': recipe._ingredients
            })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()
        new_recipe.update_grade()
        new_recipe.put()

        # Update recipe ranking for sorting
        recipe.update_grade()
        recipe.put()

        action = UserAction()
        action.owner = self.user
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({'status': 'ok', 'redirect': new_recipe.url})