Esempio n. 1
0
def app(message: Message):
    global DRIVER
    text = message.body["text"]
    argv = shlex.split(text.split("$app", 1)[1], posix=True)

    output_list = []
    with contextlib.redirect_stdout(StringIO()) as o:
        with contextlib.redirect_stderr(o):
            try:
                if DRIVER is None:
                    parser = Parser(prog="$app")
                    DRIVER = runtime.Driver(parser=parser)
                    DRIVER.run(argv, module=sys.modules[__name__], debug=True)
                else:
                    DRIVER._run(argv, debug=True)
            except Exit as e:
                logger.debug("exit: %r", e)

    output = o.getvalue()
    if output.strip():
        output_list.append(output)

    new_line = "\n"
    if output_list:
        message.send(f"""\
```
{new_line.join(output_list).strip(new_line)}
```""")
Esempio n. 2
0
def hello_send(message: Message):
    import shlex

    text = message.body["text"]
    parser = Parser(prog="$hello")
    Injector(hello).inject(parser)

    argv = shlex.split(text.split("$hello", 1)[1], posix=True)
    try:
        args = parser.parse_args(argv)
    except Exit as e:
        texts = []
        if e.args[0]:
            texts.append(e.args[0])
        texts.append(parser.format_help())
        new_line = "\n"
        message.send(f"""\
```
{new_line.join(texts).strip(new_line)}
```""")
        return

    params = vars(args).copy()
    with contextlib.redirect_stdout(StringIO()) as o:
        hello(**params)
    output = o.getvalue()
    if output.strip():
        message.send(output)
Esempio n. 3
0
def describe_handler(message: Message, command, entry_no):
    logging.info(message.body)

    if entry_no is None or entry_no == '':
        message.send(f"{command} のあとに登録番号(半角数字のみ)を入力してください")
        return

    Describe().specified_entry_no(message, entry_no)
Esempio n. 4
0
    def __validate_book_price(self, book_price: str, message: Message) -> bool:
        """
        立替金額のバリデーション
        :param book_price: 立替金額
        :return:
        """
        if not book_price.isdecimal():
            message.send("立替金額は数字で入力してください", thread_ts=message.body['ts'])
            return False

        return True
Esempio n. 5
0
def hello(msg: Message, number_of_die: str, side_of_die: str):
    #
    roll_result = [
        random.randrange(1, int(side_of_die), 1)
        for i in range(int(number_of_die))
    ]

    # 주사위를 던진 횟수만큼 나온 숫자를 모두 더합니다.
    roll_sum = sum(roll_result)

    # 주사위를 던져서 나온 숫자와 합을 메시지로 출력합니다.
    msg.send(str(roll_result))
    msg.send(str(roll_sum))
Esempio n. 6
0
def botsend(message: Message, text: str) -> None:
    """
    スレッドの親かどうかで応答先を切り替える message.send() の代わりの関数

    :param messsage: slackbotのmessageオブジェクト
    :param text: 送信するテキストメッセージ
    """
    if "thread_ts" in message.body:
        # スレッド内のメッセージの場合
        message.send(text, thread_ts=message.thread_ts)
    else:
        # 親メッセージの場合
        message.send(text, thread_ts=None)
Esempio n. 7
0
def hello(msg: Message, number_of_die: str, side_of_die: str):

    # 'roll 던지는횟수d숫자면체' 로
    # '던지는횟수'를 number_of_die
    # '숫자면체'를 side_of_die
    # '
    roll_result = [
        random.randrange(1, int(side_of_die), 1)
        for i in range(int(number_of_die))
    ]
    roll_sum = sum(roll_result)

    msg.send(str(roll_result))
    msg.send(str(roll_sum))
Esempio n. 8
0
def delete_handler(message: Message, command, entry_no):
    logging.info(message.body)

    if message.body['channel'] != settings.DEFAULT_CHANNEL_ID:
        slack = Slack()
        text = f"公式チャンネル #{slack.get_channel_name(message, channel_id=settings.DEFAULT_CHANNEL_ID)} で実行してください!"
        slack.send_message_with_link_names(message, message.body['channel'],
                                           text)
        return

    if entry_no is None or entry_no == '':
        message.send(f"{command} のあとに登録番号(半角数字のみ)を入力してください")
        return

    Delete().specified_entry_no(message, entry_no)
Esempio n. 9
0
def plusplus_delete(message: Message, subcommand: str, name: str) -> None:
    """
    指定された名前を削除する
    カウントが10未満のもののみ削除する
    """

    try:
        plus = Plusplus.get(name=name)
    except Plusplus.DoesNotExist:
        message.send(f"`{name}` という名前は登録されていません")
        return

    if abs(plus.counter) > 10:
        botsend(message,
                f"`{name}` のカウントが多いので削除を取り消しました(count: {plus.counter})")
        return

    plus.delete_instance()
    message.send(f"`{name}` を削除しました")
Esempio n. 10
0
def plusplus_rename(message: Message, old: str, new: str) -> None:
    """
    指定された old から new に名前を変更する
    """
    try:
        oldplus = Plusplus.get(name=old)
    except Plusplus.DoesNotExist:
        botsend(message, f"`{old}` という名前は登録されていません")
        return

    newplus, created = Plusplus.get_or_create(name=new,
                                              counter=oldplus.counter)
    if not created:
        # すでに存在している
        message.send(f"`{new}` という名前はすでに登録されています")
        return

    # 入れ替える
    oldplus.delete_instance()
    botsend(message,
            f"`{old}` から `{new}` に名前を変更しました(count: {oldplus.counter})")
Esempio n. 11
0
def hello_send(message: Message):
    import shlex

    text = message.body["text"]
    parser = Parser(prog="$hello")
    parser.add_argument("--name", default="world")
    argv = shlex.split(text.split("$hello", 1)[1], posix=True)
    try:
        args = parser.parse_args(argv)
        print(f"parsed: {args}", file=sys.stderr)
        message.send(f"hello {args.name}")
    except Exit as e:
        texts = []
        if e.args[0]:
            texts.append(e.args[0])
        texts.append(parser.format_help())
        new_line = "\n"
        message.send(f"""\
```
{new_line.join(texts).strip(new_line)}
```""")
Esempio n. 12
0
def hello_send(message: Message):
    import re

    text = message.body["text"]
    parser = Parser()
    parser.add_argument("--name", default="world")
    argv = [x for x in re.split(r"\s+", text.split("$hello", 1)[1]) if x]
    try:
        args = parser.parse_args(argv)
        print(f"parsed: {args}", file=sys.stderr)
        return message.send(f"hello {args.name}")
    except Exit as e:
        texts = []
        if e.args[0]:
            texts.append(e.args[0])
        texts.append(parser.format_help())
        new_line = "\n"
        return message.send(
            f"""\
```
{new_line.join(texts)}
```"""
        )
Esempio n. 13
0
def late_count(message_info: Message):
    message = message_info.body['text']
    if message.find('이번달') != -1:
        target_date = date.today()
    else:
        try:
            target_date = parse(message, fuzzy=True).date()
        except ValueError:
            target_date = date.today() - relativedelta(months=1)

    slacker = Slacker(settings.API_TOKEN)
    channel_id = message_info.channel._body['id']
    response = slacker.groups.history(channel_id, count=1000)
    messages = response.body['messages']

    late_info = get_late_count_dict(channel_id, messages, target_date)

    if message.find('상세') != -1:
        message = make_late_count_detail_message(target_date, late_info)
    else:
        message = make_late_count_message(target_date, late_info)

    message_info.send(message)
Esempio n. 14
0
    def save(self, message: Message):
        now = datetime.now()

        entry_no = ''
        impression = ''
        for block in message.body['blocks']:
            if not ('text' in block and 'text' in block['text']):
                continue

            text = block['text']['text']
            if '*登録番号*' in text:
                entry_no = re.sub('\\D', '', self.converter.to_hankaku(text))
                self.logger.debug(f"entry_no={entry_no}")
            elif '*感想*' in text:
                impression = re.sub('\*感想\*\n', '', text).strip()
                self.logger.debug(f"impression={impression}")

        # 投稿タイムスタンプ(スレッド投稿のため)
        ts = message.body['ts']

        # パラメータチェック
        if not self.validation.validate_impression(entry_no=entry_no, message=message):
            self.logger.debug("パラメータチェックNG")
            return

        # 申請者 Slack ID
        slack_id = self.slack.get_slack_id_from_workflow(message.body['text'])

        # 更新対象レコードを取得
        items = self.dynamodb.query_specified_key_value(self.dynamodb.default_table, 'entry_no', entry_no)
        # プライマリキー指定なので必ず1件取得
        item = items[0]

        if item['slack_id'] != slack_id:
            message.send(f"<@{slack_id}> 購入者本人以外は感想登録できません!", thread_ts=ts)
            return False

        # 感想登録日
        impression_time = now.strftime("%Y%m%d%H%M%S")
        self.logger.debug(f"impression_time={impression_time}")

        # 感想登録フラグ 1:登録あり
        impression_flag = '1'

        # 感想登録
        response = self.dynamodb.update_bookbot_entry_impression(entry_no, impression, impression_time, impression_flag)
        self.logger.debug(response)
        if response is None:
            self.logger.error(f"感想の登録に失敗しました")
            message.send(f"<@{slack_id}> 感想の登録に失敗しました...すいません!", thread_ts=ts)
            return False

        item['impression'] = impression
        reply_texts = [f"<!here> 以下の感想が登録されました!"]
        reply_texts.append(self.converter.get_list_str(item))

        message.send("\n".join(reply_texts), thread_ts=ts)
Esempio n. 15
0
def hello(msg: Message):
    msg.send("world!!")
Esempio n. 16
0
def hello(msg: Message):
    msg.send("World!")
Esempio n. 17
0
    def __validate_entry_no(self, entry_no: str, message: Message) -> bool:
        if not entry_no.isdecimal():
            message.send("登録番号は数字で入力してください", thread_ts=message.body['ts'])
            return False

        return True
Esempio n. 18
0
    def save(self, message: Message):

        now = datetime.now()

        book_name = ''
        book_type = ''
        book_price = ''
        book_url = ''
        purpose = ''
        for block in message.body['blocks']:
            if not ('text' in block and 'text' in block['text']):
                continue

            text = block['text']['text']
            if '*題名*' in text:
                book_name = re.sub('\*題名\*|\n', '', text)
                self.logger.debug(f"book_name={book_name}")
            elif '*形式*' in text:
                book_type = re.sub('\*形式\*|\n', '', text)
                self.logger.debug(f"book_type={book_type}")
            elif '*立替金額(税込)*' in text:
                book_price = re.sub('\\D', '', self.converter.to_hankaku(text))
                self.logger.debug(f"book_price={book_price}")
            elif '*詳細リンク(Amazonなど)*' in text:
                book_url = re.sub('\*詳細リンク(Amazonなど)\*|<|>|\n', '', text)
                self.logger.debug(f"book_url={book_url}")
            elif '*購入目的*' in text:
                purpose = re.sub('\*購入目的\*|<|>|\n', '', text)
                self.logger.debug(f"purpose={purpose}")

        # 投稿タイムスタンプ(スレッド投稿のため)
        ts = message.body['ts']

        # パラメータチェック
        if not self.validation.validate_entry(book_name=book_name, book_price=book_price, book_url=book_url, message=message):
            self.logger.debug("パラメータチェックNG")
            return

        # 申請日
        entry_time = now.strftime("%Y%m%d%H%M%S")

        # 申請者 Slack ID
        slack_id = self.slack.get_slack_id_from_workflow(message.body['text'])

        # 申請者名
        user_name = self.slack.get_user_name(slack_id, message)
        slack_name = user_name[0]
        real_name = user_name[1]

        # 今年度の合計立替金額を取得
        total_price_in_this_year = self.amount.get_total_price_in_this_year(slack_name)
        # そのユーザが年間上限金額以上立替していないか
        result = self.amount.check_max_amount(slack_name, book_price, total_price_in_this_year)
        # 今回申請分を登録する前の 残り金額
        remain_amount = self.amount.get_remain_amount(slack_name, total_price_in_this_year)
        if not result:
            self.logger.debug("年間立替金額上限を超えています")
            message.send(f"<@{slack_id}> 年間立替金額上限を超えるため登録できません。残り *{remain_amount}* 円 までならOKです。", thread_ts=ts)
            return

        # 受付番号
        # アトミックカウンタでシーケンス番号を発行し文字列として取得する
        entry_no = str(self.dynamodb.atomic_counter('atomic-counter', 'entry_no'))

        # 今年度の合計立替金額に今回申請分を足す
        total_price_in_this_year += int(book_price)
        # 今回申請分を登録した後の 残り金額
        remain_amount = self.amount.get_remain_amount(slack_name, total_price_in_this_year)

        # パーマリンクを取得
        permalink = self.slack.get_message_permalink(message)

        # 感想(空で登録)
        impression = ''
        impression_flag = '0'  # 0:登録無し

        item = {
            'entry_no': entry_no,
            'book_name': book_name,
            'book_type': book_type,
            'book_price': book_price,
            'total_price_in_this_year': total_price_in_this_year,
            'remain_amount': remain_amount,
            'book_url': book_url,
            'purpose': purpose,
            'entry_time': entry_time,
            'slack_id': slack_id,
            'slack_name': slack_name,
            'real_name': real_name,
            'permalink': permalink,
            'impression': impression,
            'impression_flag': impression_flag
        }
        self.logger.info(f"item={item}")

        self.dynamodb.insert(self.dynamodb.default_table, item)

        reply_texts = [f"<@{slack_id}> 登録しました!"]
        reply_texts.append(f"登録番号: *[{entry_no}]*")
        reply_texts.append(f"今年度の立替金額合計が *{total_price_in_this_year}* 円になりました。")
        if remain_amount == 0:
            reply_texts.append(f"上限金額は *{self.amount.max_amount}* 円です。今年度はこれが最後の立替になります。")
        else:
            reply_texts.append(f"残り *{remain_amount}* 円 までならOKです。")

        if book_price == '0':
            self.logger.info("0円のため承認PDFは作成しません")
            message.send("\n".join(reply_texts), thread_ts=ts)
            return

        reply_texts.append('補助対象になりますので承認PDFを作成します。')
        message.send("\n".join(reply_texts), thread_ts=ts)

        # 承認内容のPDFを作成してSlackにアップ バックアップでS3にアップ
        # 保存先PDFファイルパス
        save_pdf_fname = f"{entry_no}_{entry_time}_{slack_name}.pdf"
        save_pdf_path = f"{app_home}/output_pdf/{save_pdf_fname}"
        # 承認PDF作成
        if not self.pdf.make_approved_pdf(item, save_pdf_path):
            self.logger.warning('承認PDFの作成に失敗しました')
            message.send(f"<@{item['slack_id']}> 承認PDFの作成に失敗しました...すいません!")
            return False

        channel_name = self.slack.get_channel_name(message)
        self.logger.debug(channel_name)

        self.slack.upload_file(message, channel_name,
                               fpath=save_pdf_path,
                               comment="このPDFと購入時の領収書を添付して立替金申請をしてください。",
                               thread_ts=ts)

        # S3にもアップロード
        this_year = self.converter.get_this_year_from_today()[0][0:4]  # 今年度のYYYY
        self.s3.upload_to_pdf(save_pdf_path, process_yyyy=this_year)