def _create_meal(self, slack_user: SlackUser, meal_name: str, response_url: str):
        user = Commands.user(slack_user)
        restaurant = \
            Restaurant.objects.get_or_create(name=Restaurant.ADHOC_NAME, provider='None', url='', enabled=False)[0]
        meal = Meal.objects.create(name=meal_name, price=None, restaurant=restaurant)
        Selection.objects.create(meal=meal, user=user, recommended=False)

        self._sender.post_selections(Commands.today_selections())
        for u in User.objects.filter(enabled=True).all():
            self._sender.send_meals(u, [restaurant])

        self._sender._api.send_response(response_url, {"response_type": "ephemeral", "text": "created and voted for"})
    def _list_restaurants(self, slack_user: SlackUser):
        user = Commands.user(slack_user, allow_create=False)
        if user:
            selected_restaurants_ids = {r.pk for r in user.all_favorite_restaurants()}
        else:
            selected_restaurants_ids = None

        text = "*Available Restaurants*"
        return {
            "response_type": "ephemeral",
            "text": text,
            "blocks": SlackSender.restaurant_blocks(text, Commands.all_restaurants(), selected_restaurants_ids)
        }
Exemplo n.º 3
0
def dashboard(request: HttpRequest):
    selections = Commands.today_selections()
    restaurant_users = [(s.meal.restaurant.name, s.user) for s in selections
                        if s.meal.restaurant.name != Restaurant.ADHOC_NAME]
    adhoc_meal_users = [(s.meal.name, s.user) for s in selections
                        if s.meal.restaurant.name == Restaurant.ADHOC_NAME]

    def group(name_user_list: List[Tuple[str, User]]):
        name_users_grouped = [
            (name, {name_user[1]
                    for name_user in name_users})
            for name, name_users in itertools.groupby(
                sorted(name_user_list, key=lambda y: y[0]), lambda y: y[0])
        ]
        return [{
            'name': name,
            'users': users
        } for name, users in sorted(name_users_grouped,
                                    key=lambda name_users:
                                    (-len(name_users[1]), name_users[0]))]

    context = {
        'selections': group(restaurant_users) + group(adhoc_meal_users),
    }
    return render(request, 'dashboard.html', context=context)
    def _search_meals(slack_user: SlackUser, query: str):
        user = Commands.user(slack_user)
        if user:
            user_meals_pks = {s.meal.pk for s in user.selections.filter(meal__date=date.today()).all()}
        else:
            user_meals_pks = None

        user_restaurants = user.all_favorite_restaurants()
        other_restaurants = Restaurant.objects.exclude(id__in=[r.id for r in user_restaurants]).all()

        query_words = [unidecode(w).lower() for w in query]

        found_meals = {}

        for rest in chain(user_restaurants, other_restaurants):
            res_meals = []
            for meal in rest.meals.filter(date=date.today()).all():
                normalized_name = unidecode(meal.name).lower()
                if any(w in normalized_name for w in query_words):
                    res_meals.append(meal)
            if res_meals:
                found_meals[rest.name] = res_meals

        joined_query = ', '.join(query)
        text = f"*Found meals for _'{joined_query}'_*" if found_meals else f"*No {joined_query} for you today :(*"
        return {
            "response_type": "ephemeral",
            "text": text,
            "blocks": SlackSender.search_blocks(text, query_words, found_meals, user_meals_pks)
        }
    def _select_meals(self, slack_user: SlackUser, text: str):
        user = Commands.user(slack_user, allow_create=False)
        meal_groups = text.split()

        if self._re_some_digit.search(text):
            if user is None:
                return {
                    "response_type": "ephemeral",
                    "text": "You cannot vote when you have not joined Lunchinator.\n"
                            "Do so e.g. by selecting restaurants."
                }

            try:
                meals = [meal for meal_group in meal_groups for meal in self._parse_meals(meal_group)]
            except ValueError as e:
                return {"response_type": "ephemeral", "text": f"Parsing failed: {e}"}

            for meal in meals:
                selection, created = Selection.objects.get_or_create(meal=meal, user=user)
                selection.recommended = False
                selection.save()

            self._sender.post_selections(Commands.today_selections())
            return {"response_type": "ephemeral", "text": "voted"}

        else:
            blocks = []
            if user:
                user_meals_pks = {s.meal.pk for s in user.selections.filter(meal__date=date.today()).all()}
            else:
                user_meals_pks = None

            for restaurant_prefix in meal_groups:
                restaurant = self._restaurant_by_prefix(restaurant_prefix)
                if restaurant:
                    meals = restaurant.meals.filter(date=date.today()).all()
                    blocks.extend(SlackSender.restaurant_meal_blocks(restaurant, meals, user_meals_pks))
                else:
                    blocks.append(
                        {"type": "section", "text": {"type": "mrkdwn", "text": f"`{restaurant_prefix}` not found"}}
                    )

            return {
                "response_type": "ephemeral",
                "text": "*Restaurant Offers*",
                "blocks": blocks
            }
    def _erase_meals(self, slack_user: SlackUser, meal_groups: list):
        user = Commands.user(slack_user, allow_create=False)
        if user is None:
            return {
                "response_type": "ephemeral",
                "text": "You cannot erase when you have not joined Lunchinator.\n"
                        "Do so e.g. by selecting restaurants."
            }

        try:
            meals = [meal for meal_group in meal_groups for meal in self._parse_meals(meal_group)]
        except ValueError as e:
            return {"response_type": "ephemeral", "text": f"Parsing failed: {e}"}

        for meal in meals:
            selections = user.selections.filter(meal=meal)
            selections.delete()

        self._sender.post_selections(Commands.today_selections())
        return {"response_type": "ephemeral", "text": "erased"}
    def _select_restaurants(self, slack_user: SlackUser, text: str):
        user = Commands.user(slack_user, allow_create=True)

        for r_prefix in text.split():
            restaurant = self._restaurant_by_prefix(r_prefix)
            if restaurant is None:
                return {"response_type": "ephemeral", "text": f"`{r_prefix}` not found"}
            user.favorite_restaurants.add(restaurant)

        user.enabled = True
        user.save()

        # self._sender.send_meals(user, Commands.all_restaurants()) # TODO ???
        return self._list_restaurants(slack_user)
Exemplo n.º 8
0
def restart():
    # wait for Lunchinator to exit
    try:
        pid = int(options.pid)
        getCoreLogger().info("Waiting for Lunchinator (pid %s) to terminate", options.pid)
        c = 0
        while isRunning(pid) and c<100:
            time.sleep(1. / 5)
            c+=1
            if 0==c%10:
                getCoreLogger().info("Lunchinator (pid %s) still running", options.pid)
            
        if isRunning(pid):            
            getCoreLogger().info("Lunchinator (pid %s) still running, aborting restart", options.pid)
            sys.exit(1)
            
    except ValueError:
        getCoreLogger().error("Invalid pid: %d", options.pid)
    
    getCoreLogger().info("Lunchinator gone")
    # execute commands while Lunchinator is not running
    cmdString = options.commands
    if cmdString:
        getCoreLogger().info("Executing commands while Lunchinator is not running...")
        commands = Commands(getCoreLogger(), cmdString)
        commands.executeCommands()

    # restart Lunchinator
    startCmd = options.startCmd
    if startCmd:
        args = json.loads(startCmd)
        getCoreLogger().info("Restarting Lunchinator: %s", ' '.join(args))
        
        if platform.system()=="Windows":
            subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP, close_fds=True)
        else:
            subprocess.call(args, close_fds=True)
    def _recommend_meals(self, slack_user: SlackUser, count: int):
        user = Commands.user(slack_user, allow_create=False)
        rec = Recommender(user)

        if user:
            user_meals_pks = {s.meal.pk for s in user.selections.filter(meal__date=date.today()).all()}
        else:
            user_meals_pks = None

        text = "*Recommendations*"
        return {
            "response_type": "ephemeral",
            "text": text,
            "blocks": SlackSender.recommendation_blocks(text, rec.get_recommendations(count), user_meals_pks)
        }
Exemplo n.º 10
0
    def _erase_restaurants(self, slack_user: SlackUser, text: str):
        user = Commands.user(slack_user, allow_create=False)
        if user is None:
            return {
                "response_type": "ephemeral",
                "text": "You cannot erase when you have not joined Lunchinator.\n"
                        "Do so e.g. by selecting restaurants."
            }

        for r_prefix in text.split():
            restaurant = self._restaurant_by_prefix(r_prefix)
            if restaurant is None:
                return {"response_type": "ephemeral", "text": f"`{r_prefix}` not found"}
            user.favorite_restaurants.remove(restaurant)

        user.save()

        # self._sender.send_meals(user, Commands.all_restaurants()) # TODO ???
        return self._list_restaurants(slack_user)
Exemplo n.º 11
0
from django.http import HttpResponse
from django.http import HttpRequest
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
import json
from lunchinator.commands import Commands
from lunchinator.text_commands import TextCommands
from slack_api.sender import SlackSender
from lunchinator.models import Restaurant, User
from lunchinator import SlackUser
import itertools
from typing import List, Tuple

sender = SlackSender()
cmd = Commands(sender)
tcmd = TextCommands(sender)


@csrf_exempt
def endpoint(request: HttpRequest):
    action = json.loads(request.POST["payload"])
    type = action["type"]
    user = SlackUser(action["user"]["id"], action["user"]["username"])
    # action_ts = action["action_ts"]
    # message_ts = action["message_ts"]
    # response_url = action["response_url"]

    if type == "block_actions":
        trigger_id = action["trigger_id"]
        actions = action["actions"]
Exemplo n.º 12
0
 def __init__(self, sender: SlackSender):
     self._sender = sender
     self._restaurants = sorted(Commands.all_restaurants(), key=lambda r: r.name.lower())
     self._re_some_digit = re.compile('[0-9]')
     self._re_meal = re.compile(r'([^\s0-9,]+)([0-9,]+)')