def check_exist_work(dates: list, slackid: str, action: sc.Actions): """ 指定された日付とアクションに対応するシフトを返す Args: dates (list): シフトを探す日付のリスト slackid (str): 検索対象のユーザーのslackid action (ShiftController.Actions): 呼び出し元の利用目的 Returns: list: 見つかったシフトのリスト """ work_found = [] if action is sc.Actions.REQUEST: for date in dates: work_found.append( sc.get_shift(date=date, slackid=slackid, only_active=True)) elif action is sc.Actions.CONTRACT: for date in dates: work_found.append(sc.get_shift(date=date, only_requested=True)) if action is not sc.Actions.SHOWSHIFT and len(work_found) == 0: raise ShiftNotFoundError() return work_found
def request_shift(target: dict, slackid: str) -> dict: if not target: return error_message pprint(target) target_work = sc.get_shift(eventid=target["eventid"]) start_dt = target_work.start.replace( hour=int(target["start"].split(":")[0]), minute=int(target["start"].split(":")[1]), ) end_dt = target_work.end.replace( hour=int(target["end"].split(":")[0]), minute=int(target["end"].split(":")[1]) ) sc.request(target["eventid"], start_dt, end_dt) del start_dt, end_dt sc.post_message( sc.make_notice_message( slackid, sc.Actions.REQUEST, sc.get_shift(eventid=target["eventid"]), target["start"], target["end"], target["comment"], ) ) sc.record_use(slackid, sc.UseWay.BUTTONS, sc.Actions.REQUEST) return complate_request
def cui_img(args: list, slackid: str): """ /d img コマンドの中身 :param list atgs : ユーザーから与えられた引数 :param dict : 投稿する文章を含んだdict """ index = 1 shift = None date = today = dt.datetime.now().astimezone(sc.timezone) # 引数の1つ目(eventid or date)を検証 try: date = can_parse_date(args[index], today) except ValueError: if args[index] in ("-w", "-W"): pass else: return make_msg(IMG_HELPMSG) except IndexError: pass else: index += 1 # 日付をもとに画像を作る try: if args[index] in ("-w", "-W"): shift = sc.get_week_shift( base_date=date, grouping_by_week=True, fill_blank=True ) else: shift = sc.get_shift(date=date, fill_blank=True) except IndexError: shift = sc.get_shift(date=date, fill_blank=True) uploaded_file = sc.generate_shiftimg_url(shift=shift) print("ok,upload success.") sc.record_use(slackid, sc.UseWay.COMM, sc.Actions.SHOWSHIFT) show_shift = { "response_type": "ephemeral", "blocks": [ { "type": "image", "title": { "type": "plain_text", "text": uploaded_file["filename"], "emoji": True, }, "image_url": uploaded_file["url"], "alt_text": "Example Image", } ], } return show_shift
def contract_shift(target: dict, slackid: str) -> dict: if not target: return error_message original_work = sc.get_shift(eventid=target["eventid"]) start_dt = original_work.start.replace( hour=int(target["start"].split(":")[0]), minute=int(target["start"].split(":")[1]), ) end_dt = original_work.end.replace( hour=int(target["end"].split(":")[0]), minute=int(target["end"].split(":")[1]) ) sc.contract(target["eventid"], slackid, start_dt, end_dt) sc.post_message( sc.make_notice_message( slackid, sc.Actions.CONTRACT, original_work, target["start"], target["end"], target["comment"], ) ) sc.record_use(slackid, sc.UseWay.BUTTONS, sc.Actions.CONTRACT) return complate_request
def get_shift_image(slackid, value): """ シフト画像を生成,アップロードして画像を表示するメッセージを返す :param str slackid : 呼び出したユーザーのslackid """ is_day = False date = dt.datetime.now().astimezone(sc.timezone) value_dict = {"date": None, "is_day": None} print(value) if "," in value.get("action_id"): value_dict = csv_to_dict(value.get("action_id")) if value.get("block_id") == "show_shift" and value.get("type") == "datepicker": date = dt.datetime.strptime(value.get("selected_date"), "%Y-%m-%d") is_day = literal_eval(value_dict.get("is_day")) elif value.get("block_id") == "switch_type": date = dt.datetime.strptime(value_dict.get("date"), "%Y-%m-%d") is_day = literal_eval(value.get("value")) print("ok, type is button") return_block = copy.deepcopy(show_shift) if is_day: shift = sc.get_shift(date=date, fill_blank=True) else: shift = sc.get_week_shift( base_date=date, grouping_by_week=True, fill_blank=True ) uploaded_file = sc.generate_shiftimg_url(shift=shift) print("ok,upload success.") return_block["blocks"][0]["image_url"] = "{}".format(uploaded_file["url"]) return_block["blocks"][0]["title"]["text"] = "{}".format(uploaded_file["filename"]) return_block["blocks"][2]["accessory"]["initial_date"] = date.strftime("%Y-%m-%d") return_block["blocks"][2]["accessory"]["action_id"] = ",".join( ["is_day", str(is_day), "date", date.strftime("%Y-%m-%d")] ) return_block["blocks"][3]["elements"][0]["action_id"] = ",".join( ["is_day", str(is_day), "date", date.strftime("%Y-%m-%d")] ) return_block["blocks"][3]["elements"][0]["value"] = str(not is_day) sc.record_use(slackid, sc.UseWay.BUTTONS, sc.Actions.SHOWSHIFT) pprint(return_block) return return_block
def make_application_dialog(eventid: str, is_request: bool): """ 代行を依頼/請負申請のフォームをつくる :param str eventid : 代行依頼を出すシフトのeventid """ return_block = copy.deepcopy(request_dialog if is_request else contract_dialog) target = sc.get_shift(eventid=eventid) date = target.start.strftime("%m/%d") start = target.start.strftime("%H:%M") end = target.end.strftime("%H:%M") return_block["dialog"]["state"] = ( "eventid," + eventid + ",start," + start + ",end," + end + ",date," + date ) return_block["dialog"]["elements"][0]["value"] = start return_block["dialog"]["elements"][1]["value"] = end return_block["dialog"]["elements"][0]["label"] = "開始時間 - {}~".format(start) return_block["dialog"]["elements"][1]["label"] = "終了時間 - ~{}".format(end) return return_block
def make_shift_list(slack_id, request: bool, date: str = None) -> dict: """ シフトのリスト一覧を埋め込んだメッセージを返す :param str slack_id : 対象の人のslackId :param bool request : 依頼か請負かを示す。True = 依頼 :param str date : 基準の日付。"%Y-%m-%d"書式。 :return dict """ # slackのdate selectorの回答は"%Y-%m-%d"の文字列なので、dt.datetimeにconvert date = ( dt.datetime.strptime(date, "%Y-%m-%d") if date is not None else dt.datetime.now().astimezone(sc.timezone) ) # テンプレートをコピーして文言準備 # 依頼か請負かでの文言変更 made_block = copy.deepcopy(select_nearly) made_block["blocks"][0] = { "type": "section", "block_id": "select_shift", "text": { "type": "mrkdwn", "text": ("代行依頼を出すシフトを選んでください" if request else "代行依頼を受けるシフトを選んでください"), } if request else {"type": "mrkdwn", "text": "代行依頼を受けるシフトを選んでください"}, "accessory": { "type": "static_select", "action_id": str(request), "placeholder": { "type": "plain_text", "text": "この日のあなたのシフト" if request else "この日の代行依頼", "emoji": True, }, "options": [], }, } # いずれかの状態のシフト一覧を取得 shift_list = [] if request: shift_list = sc.get_shift(date=date, slackid=slack_id, only_active=True) else: shift_list = sc.get_shift(date=date, only_requested=True) # シフト一覧部分のオブジェクトをつくる for work in shift_list: # 依頼済みリストのときは名前を表示するため名前を取得 name = work.staff_name date = work.start.strftime("%m/%d") weekday = Shift.WORKDAYS_JP[work.start.weekday()] starttime = work.start.strftime("%H:%M") endtime = work.end.strftime("%H:%M") shift_block = { "text": { "type": "plain_text", "text": "{date}({weekday}) {name}{start}~{end}".format( name="" if request else name, date=date, weekday=weekday, start=starttime, end=endtime, ), "emoji": True, }, "value": work.eventid, } print(made_block["blocks"][0]["accessory"]) made_block["blocks"][0]["accessory"]["options"].append(shift_block) # リストにするシフトがなかったときはない旨を書く if not made_block["blocks"][0]["accessory"]["options"]: made_block["blocks"][0] = { "type": "section", "text": { "type": "mrkdwn", "text": ("この日にはあなたのシフトはないようです" if request else "この日には代行依頼はないようです"), }, } # このリストが依頼か代行かをflagでaction_idに記録 made_block["blocks"][1]["accessory"]["action_id"] = str(request) return made_block
def do_action( slackid: str, action: sc.Actions, date: dt.datetime, work: Work, time_range: dict, text: str, ts: str, receive_channel: str, ): """ 情報をもとにactionに対応した処理を行う Args: slackid (str): ユーザーのslackid action (ShiftController.Actions): メッセージから判定した処理 date (datetime.datetime): メッセージから判定した日付 work (Work): メッセージから抽出したシフト time_range (dict): メッセージから抽出した時間範囲 {"start": %H:%M, "end": %H:%M} text (str): メッセージの本文 ts (str): メッセージのタイムスタンプ receive_channel (str): メッセージを受け取ったチャンネルのchannel id """ if action is sc.Actions.SHOWSHIFT: image = sc.generate_shiftimg_url( shift=sc.get_shift(date=date, fill_blank=True)) print(image, file=sys.stderr) sc.post_message( "{}のシフトです".format(date.strftime("%Y/%m/%d")), attachments=[{ "image_url": image["url"], "fields": [] }], channel=receive_channel, ts=ts, ) else: if not time_range: time_range = {"start": work.start, "end": work.end} if action is sc.Actions.REQUEST: sc.request( work.eventid, time_range["start"].strftime("%H:%M"), time_range["end"].strftime("%H:%M"), ) elif action is sc.Actions.CONTRACT: sc.contract( work.eventid, slackid, time_range["start"].strftime("%H:%M"), time_range["end"].strftime("%H:%M"), ) notice_message = sc.make_notice_message(slackid, action, work, time_range["start"], time_range["end"], text) sc.post_message(notice_message) sc.record_use(slackid, sc.UseWay.CHAT, action)
def cui_con(args: list, slackid: str): """ /d con コマンドの中身 :param list atgs : ユーザーから与えられた引数 :param dict : 投稿する文章を含んだdict """ index = 1 date = today = dt.datetime.now().astimezone(sc.timezone) target = None target_time = None comment = "" # 1つ目の引数を精査する try: date = can_parse_date(args[index], today) target = sc.get_shift(date=date, only_requested=True) if len(target) == 0: return make_msg("> Error : 対象になるシフトがありません\n" + CON_HELPMSG) except ValueError: try: target = sc.get_shift(eventid=args[index]) except (ValueError, KeyError): return make_msg("> Error : targetが無効です。\n" + CON_HELPMSG) except IndexError: return make_msg(CON_HELPMSG) # 2番めの引数をチェック index += 1 try: # 時間指定オプションを確認 if args[index] == "-r": index += 1 try: # 引数の文字列が妥当かを判断 target_time, _ = check_times(target, args[index]) except TimeOverhangError: # 時刻の範囲がはみ出している return make_msg("> Error : 時刻の範囲が不適切です\n" + CON_HELPMSG) except InvalidTimeFormatError: # 与えられた文字列がHH:MM~HH:MMではない return make_msg("> Error : 時刻指定の文字列が不適切です\n" + CON_HELPMSG) except IndexError: return make_msg("> Error : rangeが不正です\n" + CON_HELPMSG) # 時間指定を受け取ったので次の引数を参照する index += 1 except IndexError: # この位置でIndexErrorならrange指定がないだけなので問題なし pass try: # 2番めor4番目とそれ以降の引数をコメントとしてまとめる comment = " ".join(args[index:]) except IndexError: # コメントは必須ではないので何もしない pass # 代行の開始時間と終了時間を整理 start = target.start if target_time is None else target_time[0] end = target.end if target_time is None else target_time[1] sc.contract(slackid=slackid, eventid=target.eventid, start=start, end=end) sc.post_message( sc.make_notice_message( slackid, sc.Actions.CONTRACT, target, start, end, comment ) ) sc.record_use(slackid, sc.UseWay.COMM, sc.Actions.CONTRACT) return make_msg( "> 代行を請け負いました。\n> date : {} \n> time: {}~{}\n> comment: {}".format( target.start.strftime("%Y-%m-%d"), start, end, comment ) )
def cui_req(args: list, slackid: str): """ /d req コマンドの中身 :param list atgs : ユーザーから与えられた引数 :param dict : 投稿する文章を含んだdict """ index = 1 date = today = dt.datetime.now().astimezone(sc.timezone) target = None target_time = None comment = "" # 1つ目の引数を精査する try: date = can_parse_date(args[index], today) target = sc.get_shift(date=date, slackid=slackid, only_active=True) if len(target) == 0: return make_msg("> Error : この日にはシフトがありません\n" + REQ_HELPMSG) except ValueError: try: target = sc.get_shift(eventid=args[index]) except ValueError: return make_msg("> Error : targetが無効です。\n" + REQ_HELPMSG) except IndexError: return make_msg(REQ_HELPMSG) # 2番めの引数をチェック index += 1 try: # 時間指定オプションを確認 if args[index] == "-r": index += 1 try: # 引数の文字列が妥当かを判断 target_time, devide = check_times(target, args[index]) except TimeOverhangError: # 時刻の範囲がはみ出している return make_msg("> Error : 時刻の範囲が不適切です\n" + CON_HELPMSG) except InvalidTimeFormatError: # 与えられた文字列がHH:MM~HH:MMではない return make_msg("> Error : 時刻指定の文字列が不適切です\n" + CON_HELPMSG) except IndexError: return make_msg("> Error : rangeが不正です\n" + CON_HELPMSG) # 時間指定を受け取ったので次の引数を参照する index += 1 # 2番めor4番目の引数をcheck if args[index]: comment = " ".join(args[index:]) except IndexError: return make_msg("> Error : commentがありません\n" + REQ_HELPMSG) # 代行の開始時間と終了時間を整理 start = target.start if target_time is None else target_time[0] end = target.end if target_time is None else target_time[1] sc.request(eventid=target.eventid, start=start, end=end) sc.post_message( sc.make_notice_message(slackid, sc.Actions.REQUEST, target, start, end, comment) ) sc.record_use(slackid, sc.UseWay.COMM, sc.Actions.REQUEST) return make_msg( "> 代行を依頼しました。\n> date : {} \n> time: {}~{}\n> comment: {}".format( target.start.strftime("%Y-%m-%d"), start, end, comment ) )