def todo_show(message, id): db = DB(os.environ['TODO_DB']) data = db.select_id(id) user = tools.getmsginfo(message)["user_id"] if data["user"] != user and data["user"] != "all": return "お探しのデータは存在しません。" if data["update_at"] != "None" and data["deleted"] == "0": msg = f"id:{id}の詳細データ\n" msg += "```" if data["user"] == "all": msg += "これは全体向けのお知らせです。\n" msg += data["title"] + "\n\n教科: " if data["subject"] == None or data["subject"] == "None": msg += "不明" else: msg += data["subject"] msg += "\n" msg += "締切: " if data["limit_at"] == "2999/12/31 23:59": msg += "無期限" else: msg += data["limit_at"] msg += "\n" msg += "状態: " + data["status"] + "\n" msg += "※備考\n " + data["note"] + "\n\n" msg += "最終更新: " + data["update_at"] + "```\n" else: msg = "お探しのデータは存在しません。" message.reply(msg)
def todo_list(user): database = DB(os.environ['TODO_DB']) data = database.dict_list_sorted(show_over_deadline=3, user_id=user) num = 0 str_list = '' now = str(datetime.datetime.now()) now_f = now.replace('-', '/')[5:16] for r in data: num += 1 if r["importance"] == '大': #もう少しわかりやすく区別したい if r["subject"] == 'None': str_list += f' _`{r["id"]}`_ _*{r["title"]}*_ 期限:{r["limit_at"][5:]}\n' else: str_list += f' _`{r["id"]}`_ _{r["subject"]}_ _*{r["title"]}*_ 期限:{r["limit_at"][5:]}\n' else: if r["subject"] == 'None': str_list += f' `{r["id"]}` *{r["title"]}* 期限:{r["limit_at"][5:]}\n' else: str_list += f' `{r["id"]}` {r["subject"]} *{r["title"]}* 期限:{r["limit_at"][5:]}\n' if str_list == '': str_list = now_f + '現在、リストには未完了のタスクが存在しません。' else: str_list = f'{now_f}現在、未完了のタスクは以下の{num}件です。\n' + str_list return str_list
def todo_list_notdone(user): database = DB(os.environ['TODO_DB']) data = database.dict_list_sorted(show_over_deadline=2, user_id=user) str_list = 'TODO list (期限切れ or 未提出):\n' for r in data: str_list += ', '.join(map(str, r.values())) str_list += '\n' return str_list
def todo_add_sub(message, data: dict, announce=False) -> str: """データ登録の際はこのtodo_add_subにmessageとデータのディクショナリを与えてください。 戻り値は、登録内容をお知らせする文字列となっています。 """ # ユーザー情報取得 if announce: data["user"] = "******" else: info = tools.getmsginfo(message) data["user"] = info["user_id"] database = DB(os.environ['TODO_DB']) has_limit = True now = datetime.datetime.now() if "limit_at" in data.keys() or not "status" in data.keys(): if not "limit_at" in data.keys() and not "status" in data.keys(): data["limit_at"] = "2999/12/31 23:59" has_limit = False limit_at_fin = tools.datetrans(data["limit_at"], now) msg = "以下の内容で" if limit_at_fin != None or data["limit_at"] == None: if data["limit_at"] != None: limit_at_format = datetime.datetime.strptime( limit_at_fin, '%Y/%m/%d %H:%M') if now > limit_at_format: data["status"] = '期限切れ' noticetime = tools.noticetimeSet(limit_at_format, now) data["noticetime"] = noticetime data["limit_at"] = limit_at_fin if has_limit: msg += "、期限を正しく設定して" else: msg += "、無期限の課題を" else: return "limit_atの形が不正です。以下の入力例を参考にしてください。\n202008161918: 2020年8月16日19時18分となります。\n0816: 現在以降で最も早い8月16日23時59分となります。" data = database.add_dict(data) msg += "追加しました。" for item in data.items(): if item[0] == "user": continue if not (item[0] == "noticetime" or item[0] == "deleted"): msg += f"\n{item[0]}: {item[1]}" return msg if "status" in data.keys(): data["noticetime"] = 3 data = database.add_dict(data) msg = "以下の内容で追加しました。\n" for item in data.items(): if item[0] == "user": continue if not item[0] == "noticetime" or item[0] == "deleted": msg += f"\n{item[0]}: {item[1]}" return msg return "何らかの不具合により追加できません。"
def todo_search(text): msg = '' num = 0 database = DB(os.environ['TODO_DB']) matched = database.search('title', text) if matched == []: msg = '一致するassigmentは存在しません' else: for data in matched: num += 1 msg += f'\n{data["title"]}, 期限:{data["limit_at"]}, status:{data["status"]}, id:{data["id"]}' msg = f'一致するassignmentは以下の{num}件です。' + msg return msg
def todo_search(message, text): msg = '' num = 0 database = DB(os.environ['TODO_DB']) matched = database.search('title', text) if matched == []: msg = '一致するassigmentは存在しません' else: for data in matched: num += 1 msg += f'\n *{data["title"]}* 期限:{data["limit_at"][5:]} status:*{data["status"]}* `{data["id"]}`' msg = f'一致するassignmentは以下の{num}件です。' + msg message.reply(msg)
def todo_cancel_announcement(id): db = DB(os.environ['TODO_DB']) result = db.delete_id(id, "all") if result == 200: msg = f"id{id}番のannouncementを削除しました。" elif result == 401: msg = f"idが不正です。" elif result == 402: msg = f"sql文が上手く実行できませんでした。" elif result == -1: msg = f"指定されたidのデータはannouncementではありません。" else: msg = "うまくいきませんでした。" return msg
def todo_delete_secret(userid, id): db = DB(os.environ['TODO_DB']) result = db.delete_id(id, userid, secret=True) if result == 200: msg = f"id{id}番を削除しました。また、id{id}番データ内容は初期化されました。" elif result == 401: msg = f"idが不正です。" elif result == 402: msg = f"sql文が上手く実行できませんでした。" elif result == -1: msg = f"他のユーザーのものは変更できません。" else: msg = "うまくいきませんでした。" return msg
def todo_delete_secret(message, id): db = DB(os.environ['TODO_DB']) userid = tools.getmsginfo(message)["user_id"] result = db.delete_id(id, userid, secret=True) if result == 200: msg = f"id{id}番を削除しました。また、id{id}番データ内容は初期化されました。" elif result == 401: msg = f"idが不正です。" elif result == 402: msg = f"sql文が上手く実行できませんでした。" elif result == -1: msg = f"他のユーザーのものは変更できません。" else: msg = "うまくいきませんでした。" message.reply(msg)
def todo_change_id(id, column, value): database = DB(os.environ['TODO_DB']) status_code = database.change_id(id, column, value) msg = '' if status_code == 400: msg = 'カラムが不正です' elif status_code == 401: msg = 'idが不正です' elif status_code == 402: msg = 'sqlite文が実行できません' elif status_code == 403: msg = 'limit_atを正しく入力してください' elif status_code == 404: msg = 'idまたはupdate_atを変更することはできません' elif status_code == 200: msg = '値を変更しました' return msg
def __notice_notdone(self): self.now = dt.datetime.now() db = DB(os.environ['TODO_DB']) self.dict_list = db.dict_list() self.channel = os.environ['SLACK_CHANNEL'] for dict in self.dict_list: # 前バージョンとの互換性を保つ if not "noticetime" in dict.keys(): continue noticetime = int(dict['noticetime']) try: self.__limit_at = dt.datetime.strptime(dict["limit_at"], '%Y/%m/%d %H:%M') # statusの更新 if self.now > self.__limit_at and dict['status'] == '未': db.change_id(dict['id'], 'status', '期限切れ') except: break color = '' text = '' post = False if dict["status"] == '未': if self.__limit_at < self.now + dt.timedelta( hours=1) and noticetime == 1: text = "期限まであと1時間。ひょっとして提出し忘れてるんじゃ?:face_with_rolling_eyes::face_with_rolling_eyes:" noticetime = 0 color = 'ff4500' post = True elif self.__limit_at < self.now + dt.timedelta( days=1) and noticetime == 2: text = "期限まであと1日もありません!!のんびりしてる暇なんてありませんね:sweat_drops:" noticetime = 1 color = 'ffff00' post = True elif self.__limit_at < self.now + dt.timedelta( days=3) and noticetime == 3: text = "期限まであと3日。そろそろとりかかろう...:sunglasses:" noticetime = 2 color = '7cfc00' post = True if post == True: attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": '*' + dict["title"] + '*\n' + '期限:' + dict["limit_at"] + '\nid:' + dict["id"] } }] }] tools.postMessage(text, attachments, channel=self.channel, icon_emoji=":panda_face:") db.change_id(dict['id'], 'noticetime', noticetime)
def todo_finish(userid, ids): msg = '' msg1 = '\nid: ' msg2 = '\nid: ' msg3 = '\nid: ' success = False failed = False others = False id = ids.split() database = DB(os.environ['TODO_DB']) for i in id: strip = i.find('|') if strip > 0: i = i[strip + 1:] i = i.replace('>', '') data = database.select_id(i) if data["user"] == None: msg2 += '`' + i + '` ' failed = True continue elif userid != data["user"]: msg3 += '`' + i + '` ' others = True continue status_code = database.change_id(i, 'status', '済') if status_code == 200: msg1 += '`' + i + '` ' success = True if success and failed and others: msg = msg1 + 'を完了しました。お疲れ様でした。' + msg2 + 'は存在しません。' + msg3 + 'は他人のタスクです。' elif success and failed: msg = msg1 + 'を完了しました。お疲れ様でした。' + msg2 + 'は存在しません。' elif failed and others: msg = msg2 + 'は存在しません。' + msg3 + 'は他人のタスクです。' elif success: msg = msg1 + 'を完了しました。お疲れ様でした。' elif failed: msg = msg2 + 'は存在しません。' elif others: msg = msg3 + 'は他人のタスクです。' else: msg = 'このコマンドは実行できません。' return msg
def pandaThread(user, esc_id, password, channel, ts): panda_database_names[user] = DB(os.environ["TODO_DB"]) status_code = autoadd.main(user=user, username=esc_id, password=password, database=panda_database_names[user]) if status_code == 400: slack_bot_client.chat_update(channel=channel, text='esc-idまたはパスワードが間違っています。\n/pandaコマンドを入力して再登録してください', ts=ts) elif status_code == 200: print('pandaThread終了') try: slack_bot_client.chat_update(channel=channel, text='更新が終了しました', ts=ts) msg = todo.todo_list(user) slack_bot_client.chat_update(channel=channel, text=msg, ts=ts) except: print('failed') del panda_database_names[user]
def todo_add(message, title, limit_at): # ユーザー情報取得 info = tools.getmsginfo(message) data = {"title": title, "limit_at": limit_at, "user": info["user_id"]} database = DB(os.environ['TODO_DB']) now = datetime.datetime.now() limit_at_fin = tools.datetrans(limit_at, now) msg = "以下の内容で" if limit_at_fin != None: limit_at_format = datetime.datetime.strptime(limit_at_fin, '%Y/%m/%d %H:%M') if now > limit_at_format: data["status"] = '期限切れ' noticetime = tools.noticetimeSet(limit_at_format, now) data["noticetime"] = noticetime data["limit_at"] = limit_at_fin msg += "、期限を正しく設定して" data = database.add_dict(data) msg += "追加しました。" for item in data.items(): if item[0] == "user": continue msg += f"\n{item[0]}: {item[1]}" message.reply(msg)
def todo_list_notdone(message): database = DB(os.environ['TODO_DB']) userId = tools.getmsginfo(message)['user_id'] data = database.dict_list_sorted(show_over_deadline=2, user_id=userId) msg = todo_view(data, '未完了・期限切れの') message.reply(msg)
from tododb import DB import os dbname = os.environ['TODO_DB'] need_init = not os.path.exists(dbname) database = DB(dbname) if need_init: database.init() #列追加、減少を自動反映 database.clean() database.add('test-title1', '2020-06-01') print(database.list())
def todo_add_unlimit(message, title): database = DB(os.environ['TODO_DB']) database.add(title, None)
def todo_list(message): database = DB(os.environ['TODO_DB']) message.reply(database.list())
def todo_reset(message): database = DB(os.environ['TODO_DB']) database.reset() message.reply('データベースを初期化しました')
def todo_reset(): database = DB(os.environ['TODO_DB']) database.reset() return 'データベースを初期化しました'
def todo_list_all(): database = DB(os.environ['TODO_DB']) return database.list()
def __notice_notdone(self): self.now = dt.datetime.now() db = DB(os.environ['TODO_DB']) self.dict_list = db.dict_list() self.channel = os.environ['SLACK_CHANNEL'] self.notice_tasks = [] for dict in self.dict_list: # 前バージョンとの互換性を保つ if not "noticetime" in dict.keys(): continue noticetime = int(dict['noticetime']) try: self.__limit_at = dt.datetime.strptime(dict["limit_at"], '%Y/%m/%d %H:%M') # statusの更新 if self.now > self.__limit_at and dict['status'] == '未': db.change_id(dict['id'], 'status', '期限切れ') except: break color = '' text = '' post_dm = False post_announce = False attachments = [] # 全体アナウンス if dict['user'] == 'all': if self.__limit_at < self.now + dt.timedelta( hours=1) and noticetime == 1: text = '3日後の予定をお知らせします。' noticetime = 0 color = 'ff4500' post_announce = True elif self.__limit_at < self.now + dt.timedelta( days=1) and noticetime == 2: text = '1日後の予定をお知らせします。' noticetime = 1 color = 'ffff00' post_announce = True elif self.__limit_at < self.now + dt.timedelta( days=3) and noticetime == 3: text = '1時間後の予定をお知らせします。' noticetime = 2 color = '7cfc00' post_announce = True else: if dict["status"] == '未': if self.__limit_at < self.now + dt.timedelta( hours=1) and noticetime == 1: text = "期限まであと1時間。ひょっとして提出し忘れてるんじゃ?:face_with_rolling_eyes::face_with_rolling_eyes:" noticetime = 0 color = 'ff4500' post_dm = True elif self.__limit_at < self.now + dt.timedelta( days=1) and noticetime == 2: text = "期限まであと1日もありません!!のんびりしてる暇なんてありませんね:sweat_drops:" noticetime = 1 color = 'ffff00' post_dm = True elif self.__limit_at < self.now + dt.timedelta( days=3) and noticetime == 3: text = "期限まであと3日。そろそろとりかかろう...:sunglasses:" noticetime = 2 color = '7cfc00' post_dm = True if post_dm == True: dict["limit_at"] = dict["limit_at"][5:] if dict["subject"] != 'None' and dict["note"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": ' *' + dict["title"] + '* \n教科:' + dict["subject"] + '\n期限:' + dict["limit_at"] + '\n id : `' + str(dict["id"]) + '`' } }, { "type": "context", "elements": [{ "type": "plain_text", "text": "※備考\n" + dict["note"] }] }] }] elif dict["subject"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": ' *' + dict["title"] + '* \n教科:' + dict["subject"] + '\n期限:' + dict["limit_at"] + '\n id : `' + str(dict["id"]) + '` ' } }] }] elif dict["note"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": ' *' + dict["title"] + '* \n期限:' + dict["limit_at"] + '\n id : `' + str(dict["id"]) + '` ' } }, { "type": "context", "elements": [{ "type": "plain_text", "text": "※備考\n" + dict["note"] }] }] }] else: attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": ' *' + dict["title"] + '* \n期限:' + dict["limit_at"] + '\n id : `' + str(dict["id"]) + '` ' } }] }] if post_announce == True: dict["user"] = self.channel dict["limit_at"] = dict["limit_at"][5:] if dict["subject"] != 'None' and dict["note"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": '*' + dict["title"] + '* の情報です。\n教科:' + dict["subject"] + '\n日付:' + dict["limit_at"] } }, { "type": "context", "elements": [{ "type": "plain_text", "text": "※備考\n" + dict["note"] }] }] }] elif dict["subject"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": '*' + dict["title"] + '* の情報です。\n教科:' + dict["subject"] + '\n日付:' + dict["limit_at"] } }] }] elif dict["note"] != 'None': attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": '*' + dict["title"] + '* の情報です\n日付:' + dict["limit_at"] } }, { "type": "context", "elements": [{ "type": "plain_text", "text": "※備考\n" + dict["note"] }] }] }] else: attachments = [{ "color": color, "blocks": [{ "type": "section", "text": { "type": "mrkdwn", "text": '*' + dict["title"] + '* の情報です\n日付:' + dict["limit_at"] } }] }] if post_announce or post_dm: # tools.postMessage(text, attachments, channel=dict['user'], icon_emoji=":panda_face:") db.change_id(dict['id'], 'noticetime', noticetime) self.notice_tasks.append({ "text": text, "attachments": attachments, "channel": dict["user"] }) return self.notice_tasks
from slackbot.bot import Bot from tododb import DB from plugins.notice import Notice import os import threading import datetime import time import sys slack = Slacker(os.environ['API_TOKEN']) channel = os.environ['SLACK_CHANNEL'] slack.chat.post_message(channel, 'new version bot is deployed.', as_user=True) dbname = os.environ['TODO_DB'] need_init = not os.path.exists(dbname) database = DB(dbname) if need_init: database.init() def noticeThread(): time.sleep(10) while True: nt = Notice() del nt # デバックを容易にするため、待機は30秒のみ time.sleep(30) def botThread(): mybot = Bot()
def slack_app(): if not signature_verifier.is_valid_request(request.get_data(), request.headers): return make_response("invalid request", 403) if "payload" in request.form: payload = json.loads(request.form["payload"]) user_id = payload["user"]["id"] if payload["type"] == "view_submission" \ and payload["view"]["callback_id"] == "login": # Handle a data submission request from the modal submitted_data = payload["view"]["state"]["values"] # {'block-id': {'action_id': {'type': 'plain_text_input', 'value': 'your input'}}} esc_id = submitted_data['esc_id']['esc_id']['value'] password = submitted_data['password']['password']['value'] status_code = user_database.change_id(user_id, esc_id, password) if status_code == 300: status_code = user_database.add(user_id, esc_id, password) if status_code == 400: slack_bot_client.chat_postMessage(text='登録に失敗しました。', channel=user_id, as_user=True) print('failed') return make_response("", 400) # if status_code == 200 or status_code == 300: # chat = slack_bot_client.chat_postMessage(channel=user_id, text='更新中...しばらくお待ちください', as_user=True) # login_data = user_database.select_id(user_id) # # def pandaThread(): # # login_data = user_database.select_id(user_id) # # panda_database_names[user_id] = DB(os.environ["TODO_DB"]) # # status_code = autoadd.main(user=login_data["id"], username=login_data["esc_id"], password=login_data["password"], database=panda_database_names[user_id]) # # if status_code == 400: # # slack_bot_client.chat_update(channel=chat["channel"], text='esc-idとパスワードが間違っています。\n/pandaコマンドを入力して再登録してください', ts=chat["ts"], as_user=True) # # elif status_code == 200: # # print('pandaThread終了') # # if chat != None: # # slack_bot_client.chat_update(channel=chat["channel"], text='更新が終了しました', ts=chat["ts"], as_user=True) # # msg = todo.todo_list(user_id) # # slack_bot_client.chat_postMessage(channel=chat["channel"], text=msg, as_user=True) # if panda_sched.get_job(user_id) != None: # panda_sched.remove_job(user_id) # panda_sched.add_job(func=pandaThread, trigger='interval', minutes=30, id=login_data["id"], next_run_time=datetime.datetime.now()) return make_response("", 200) elif payload["type"] == "block_actions": task_user = payload["actions"][0]["block_id"] text = '' channel = payload["channel"]["id"] if payload["actions"][0]["value"] == 'finished': task_id = payload["actions"][0]["action_id"] if task_user == user_id: database = DB(os.environ["TODO_DB"]) database.change_id(task_id, 'status', '済') text = 'id:' + task_id + 'を完了しました' elif payload["actions"][0]["value"] == 'unfinished': task_id = payload["actions"][0]["action_id"][1:] if task_user == user_id: database = DB(os.environ["TODO_DB"]) database.change_id(task_id, 'status', '未') text = 'id:' + task_id + 'を未完了に変更しました' slack_bot_client.chat_postMessage(channel=channel, text=text) return make_response("", 200) return make_response("", 404)
from tododb import DB from plugins.notice import Notice from plugins import shorturl from plugins import tools from apscheduler.schedulers.background import BackgroundScheduler import atexit user_dbname = os.environ["USER_DB"] user_need_init = not os.path.exists(user_dbname) user_database = UserDB(user_dbname) if user_need_init: user_database.init() dbname = os.environ['TODO_DB'] need_init = not os.path.exists(dbname) database = DB(dbname) if need_init: database.init() database.clean() def noticeThread(): nt = Notice() del nt panda_database_names = {} sched = BackgroundScheduler(daemon=True) panda_sched = BackgroundScheduler(deamon=True) sched.add_job(func=noticeThread, trigger='interval', seconds=60) sched.start() panda_sched.start()