def put_library(): """ Create favorite library on record. It must be unique on one user record. """ body = request.get_json() id_token = body.get("idToken") libid = body.get("libid") logger.info(body) document, status_code = get_resource(resource_name="ALL", id_token=id_token) if status_code == 200: registered_favolib = document["favolib"] registered_libid = list(map(lambda favolib: favolib["libid"], registered_favolib)) if libid in registered_libid: # 406: not acceptable return jsonify({"status": 406, "message": "This library is already registered."}), 406 else: libinfo = db.library.find(libid) lib_doc = dict() lib_doc["timestamp"] = int(time.time()) lib_doc["formal"] = libinfo["formal"] lib_doc["libid"] = libinfo["libid"] lib_doc["systemid"] = libinfo["systemid"] logger.debug(f"additional favorite library: {lib_doc}") document["favolib"].append(lib_doc) resource, status_code = create_resource(document, id_token) return jsonify(resource), status_code else: return jsonify({"status": 500, "message": "api server error"}), 500
def add_bookmark(event=None): """ Register new bookmark at specified user. Parameters ---------- event: LINE event LINE event Returns ------- status: str Return status string. Raises ------ UserNotFound Raises UserNotFound if user is not registered. DuplicateBookError Raises DuplicateLibraryError if new book is already registered. """ bookmeta = record.bookmeta book_doc = record.book_doc status = "" userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() postback_data = event.postback.data.replace( "'", '"') # replace single quotation to double waitingbook = json.loads(postback_data) if db.user.find(hashed_userid) is None: raise UserNotFound user_doc = db.user.find(hashed_userid) bookmark = user_doc["bookmark"] logger.debug(f"registared bookmarks: {bookmark}") if waitingbook["isbn"] in list( map(lambda x: x["bookmeta"]["isbn"], bookmark)): raise DuplicateBookError bookmeta["title"] = waitingbook["title"] bookmeta["author"] = waitingbook["author"] bookmeta["isbn"] = waitingbook["isbn"] book_doc["timestamp"] = int(time.time()) book_doc["bookmeta"] = bookmeta logger.debug(f"addtional book marks: {book_doc}") bookmark.append(book_doc) user_doc["bookmark"] = bookmark db.user.set(hashed_userid, user_doc) # update bookmarks logger.info(f"{bookmark} is registared") status = "本が登録されました" return status
def create_resource(resource, id_token=None): id_token = id_token or os.getenv("DEFAULT_HASHED_USERId") try: response = get_profile(id_token) userid = response["sub"] hashed_useid = sha256(userid.encode()).hexdigest() logger.debug(hashed_useid) db.user.set(hashed_useid, resource) return {"status": 200}, 200 except Exception as e: logger.info(f"undefined error: {e}") return {"status": 500, "message": str(e)}, 500
def img2message(event=None): try: img = line_bot_api.get_message_content(event.message.id).content isbn = img2isbn(BytesIO(img)) logger.info(f"ISBN detected: {isbn}") isbn2message(event, isbn) except IsbnNotFound: logger.info("isbn not found") except BookNotFound: logger.info("book not found") except Exception as e: logger.info(e)
def put_options(): """ Create favorite library on record. It must be unique on one user record. """ body = request.get_json() id_token = body.get("idToken") options = body.get("items") logger.info(body) document, status_code = get_resource(resource_name="ALL", id_token=id_token) if status_code == 200: registered_options = document["options"] for key, val in options.items(): registered_options[key] = val document["options"] = registered_options logger.debug(document) resource, status_code = create_resource(document, id_token) return jsonify(resource), status_code else: return jsonify({"status": 500, "message": "api server error"}), 500
def add_history(event=None, bookdoc=None): """ Register new history at specified user. Parameters ---------- event: LINE event LINE event libinfo: dict New library book document. Returns ------- None Raises ------ None """ userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() user_doc = db.user.find(hashed_userid) history = user_doc["history"] try: logger.debug(f"hashed userid: {hashed_userid}, history: {history}") history.append(bookdoc) logger.debug(f"registaring history: {bookdoc}") user_doc["history"] = history db.user.set(hashed_userid, user_doc) # update history logger.debug(f"successed in registaring history") except Exception as e: logger.info(e)
def followevent(event=None): user_doc = record.user # copy the record to save user information userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() user_doc["userid"] = hashed_userid user_doc["context"] = "" user_doc["options"] = { "calil": True, "google": False, "honto": False, "amazon": True, "rakuten": False, "yodobashi": False, "yahoo": False, "mercari": True, "rakuma": False, "paypayfleamarket": False } status = "" try: logger.debug(user_doc) if db.user.find(hashed_userid): raise DuplicateUserError db.user.set(hashed_userid, user_doc) logger.info("Successed in registaring new follower!") status = """登録ありがとうございます。\nメニューにて"Help"を参照してください。""" except DuplicateUserError: logger.info("This user is already registared.") status = "This user is already registared" except Exception as e: logger.info("Faild to registaring new follower!") logger.info(e) status = "Fail" finally: if event: line_bot_api.reply_message( event.reply_token, messages=TextSendMessage(text=status) ) return status
def unfollowevent(event=None): userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() status = "" try: if db.user.find(hashed_userid) is None: raise UserNotFound db.user.remove(hashed_userid) logger.info("Successed in removing follower!") status = "削除" except UserNotFound: logger.info("This user is not registared.") status = "This user is not registared." except Exception as e: logger.info("Faild to removing a follower!") logger.info(e) status = "Fail" return status
def add_bookmark(event=None): try: status = add.bookmark(event) except DuplicateUserError: logger.info("This user is already registared.") status = "This user is already registared" except DuplicateBookError: logger.info("This book is already registared.") status = "This book is already registared" except UserNotFound: logger.info("Users are not found.") status = "Users are not found." except Exception as e: logger.info(e) status = "fail" finally: if event: line_bot_api.reply_message(event.reply_token, messages=TextSendMessage(text=status))
def add_library(event=None, libinfo=None): try: status = add.favolib(event, libinfo) except InvalidName: logger.info("This user is not registared.") status = "This user is not registared" except DuplicateLibraryError: logger.info("This library is already registared.") status = "This library is already registared" except Exception as e: logger.info(e) status = "fail" finally: if event: line_bot_api.reply_message(event.reply_token, messages=TextSendMessage(text=status))
def chat(event=None): # user_doc = record.user # copy the record to save user information # userid = event.source.user_id if event else "testid" # hashed_userid = sha256(userid.encode()).hexdigest() text = event.message.text if event else "some text" status = "" try: cmd = text.split(" ") if event.reply_token == "00000000000000000000000000000000": event = None return 200 elif cmd[0] == "help": status = HELP elif cmd[0].replace("-", "").isdigit() and len(cmd[0].replace( "-", "")) == 13: isbn2message(event, cmd[0].replace("-", "")) event = None else: status = "すみません、よくわかりません。" logger.info("Successed chatting!") except DuplicateLibraryError: status = "This library is already registared" except Exception as e: logger.info("Faild to registaring new follower!") logger.info(e) status = "Fail" finally: if event: line_bot_api.reply_message(event.reply_token, messages=TextSendMessage(text=status)) return status
def bookstatus(bookstatus): """ Create from bookstatus to flexbox and return it. Parameters ---------- bookstatus: list List of bookstatus which is searched in different libraries. Returns ------- flex_message: dict Carousel flex message. Raises ------ BookNotFound There is no information in calil website. """ flexboxes = [] for status, systemid in bookstatus: flex_bookstatus = deepcopy(flexbox.flex_bookstatus) try: flex_bookstatus["hero"]["url"] = "https://3.bp.blogspot.com/-FJiaJ8gidCs/Ugsu-rSFw0I/AAAAAAAAXNA/JFiIUoxggW4/s800/book_tate.png" """ if os.path.exists(f"./flaskr/static/images/library/{systemid}.jpg"): flex_bookstatus["hero"]["url"] = f"/static/images/library/{systemid}.jpg" else: flex_bookstatus["hero"]["url"] = "https://3.bp.blogspot.com/-FJiaJ8gidCs/Ugsu-rSFw0I/AAAAAAAAXNA/JFiIUoxggW4/s800/book_tate.png" """ library = db.library.filter("systemid", "==", systemid) libid = list(library.keys())[0] minitext = deepcopy(flexbox.minitext) systemname = library[libid]["systemname"] # both reserveurl and libkey are None if (status.get("reserveurl") and status.get("libkey")) is False: minitext["text"] = f"{systemname}: 在書" flex_bookstatus["body"]["contents"].append(minitext) else: minitext["text"] = systemname minitext["size"] = "lg" minitext["weight"] = "bold" flex_bookstatus["body"]["contents"].append(minitext) if status.get("libkey"): text = "" keylist = status["libkey"].keys() # status depends on libraries minitext = deepcopy(flexbox.minitext) for libkey in keylist: # short = library[libid]["short"] if library else libkey state = status["libkey"][libkey] text += f"{libkey}: {state}\n" minitext["text"] = text flex_bookstatus["body"]["contents"].append(minitext) if status.get("reserveurl"): button = deepcopy(flexbox.button) button["action"]["uri"] = status["reserveurl"] flex_bookstatus["footer"]["contents"].append(button) logger.debug(flex_bookstatus) flexboxes.append(flex_bookstatus) except KeyError: pass except Exception as e: logger.info(e) if len(flexboxes) == 1: flex_message = FlexSendMessage( alt_text='book status information', contents=flexboxes[0] ) else: carousel = { "type": "carousel", "contents": flexboxes } flex_message = FlexSendMessage( alt_text='book status information', contents=carousel ) return flex_message
def isbn2message(event, isbn): """ Create from isbn to message and send it. Parameters ---------- event: LINE event LINE event isbn: str The isbn which a user input. Returns ------- None Raises ------ None """ userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() favolib = db.user.find(hashed_userid)["favolib"] logger.debug(favolib) bookstatus = [] try: bookdoc = call_api.openbd(isbn) if bookdoc: flex_message = send.bookmeta(bookdoc, hashed_userid) add.history(event, bookdoc) else: bookdoc, flex_message = send.compact_bookmeta(isbn) add.history(event, bookdoc) line_bot_api.push_message(event.source.user_id, messages=flex_message) for library in favolib: try: bookstatus.append( (call_api.calil(isbn, library["systemid"]), library["systemid"])) except BookNotFound: pass if bookstatus: # When you cannot get book meta information from google books api, you pass NoneType to this function. flex_message = send.bookstatus(bookstatus) line_bot_api.reply_message(event.reply_token, messages=flex_message) event = None else: raise BookNotFound except MetadataNotFound: pass except BookNotFound: logger.info("book not found") status = "book not found" except Exception as e: logger.info(e) status = "Fail" finally: # A message is already sent, event is None. if event: flexcontent = flexbox.notfound flexcontent["body"]["contents"][0]["text"] = status line_bot_api.reply_message(event.reply_token, messages=FlexSendMessage( alt_text=status, contents=flexcontent))
def openbd(isbn): """ Call openbd api and return book meta data. Parameters ---------- isbn: str The isbn of a book users want to know the status. It is 13 digits. Returns ------- book_doc: dict Return book_doc with status of the book specified with isbn at the library doen with systemid. Raises ------ UserNotFound Raises UserNotFound if user is not registered. DuplicateBookError Raises DuplicateLibraryError if new book is already registered. BookNotFound None of keys are found in calil api response or some unexpected exception is occured. See also -------- flaskr.models.record.bookmeta flaskr.models.record.book_doc """ url = f"https://api.openbd.jp/v1/get?isbn={isbn}" bookmeta = record.bookmeta book_doc = record.book_doc try: bookmeta["isbn"] = isbn # resourse path at the response # keyname: {path: path to resource, name: replace keyname to this name for easily understanding} necessary_keys = { "TitleText": { "path": "onix/DescriptiveDetail/TitleDetail/TitleElement/TitleText/content", "name": "title" }, "Subtitle": { "path": "onix/DescriptiveDetail/TitleDetail/TitleElement/Subtitle/content", "name": "subtitle" }, "PersonName": { "path": "onix/DescriptiveDetail/Contributor/0/PersonName/content", "name": "author" }, "ExtentValue": { "path": "onix/DescriptiveDetail/Extent/0/ExtentValue", "name": "page" }, "ResourceLink": { "path": "onix/CollateralDetail/SupportingResource/0/ResourceVersion/0/ResourceLink", "name": "image" }, "ImprintName": { "path": "onix/PublishingDetail/Imprint/ImprintName", "name": "publisher" }, "Date": { "path": "onix/PublishingDetail/PublishingDate/0/Date", "name": "publishdate" } } openbd = requests.get(url).json()[0] contain_keylist = get_keys(openbd, []) for key in necessary_keys.keys(): if key in contain_keylist: content = find_resource(openbd, necessary_keys[key]["path"], 0) else: content = "" bookmeta[necessary_keys[key]["name"]] = content book_doc["timestamp"] = int(time.time()) book_doc["bookmeta"] = bookmeta logger.debug(book_doc) except Exception as e: book_doc = "" logger.info(e) finally: return book_doc
def calil(isbn, systemid): """ Call calil api and return book status. Parameters ---------- isbn: str The isbn of a book users want to know the status. It is 13 digits. sytemid: The systemid of a library where users want to know the book status. Returns ------- book_doc: dict Return book_doc with status of the book specified with isbn at the library doen with systemid. Raises ------ BookNotFound None of keys are found in calil api response or some unexpected exception is occured. See also -------- flaskr.models.record.book_doc """ url = "http://api.calil.jp/check?&format=json&callback=no&appkey={" + os.getenv( "CALIL_API_KEY") + "}" queries = f"&isbn={isbn}&systemid={systemid}" # bookquery = json.loads(requests.get(url+queries).text) bookquery = requests.get(url + queries).json() """ Response example {"session": "ea5e50999e96d1cd4361f6e1892ff4da", "books": {"9784873117836": {"Univ_Aizu": {"status": "Cache", "reserveurl": "https://libeopsv.u-aizu.ac.jp/gate?module=search&path=detail.do&method=detail&bibId=1000014556&bsCls=0", "libkey": {"4大": "貸出中"}}}}, "continue": 0} '""" logger.debug(bookquery) try: # When status is running, you have to wait a few seconds for detail information. cnt = 0 # Call api again and again. If 10 times called, break while (bookquery["continue"] == 1 and cnt < 10): time.sleep(1) # Call by session queries = f"&session={bookquery['session']}" #bookquery = json.loads(requests.get(url+queries).text) bookquery = requests.get(url + queries).json() logger.debug(f"session: {bookquery}") cnt += 1 bookstatus = {} found = False bookquery_isbn = bookquery["books"][isbn] # If one or more keys are found, return bookstatus. for query_systemid in bookquery_isbn.keys(): reserveurl = bookquery_isbn[query_systemid].get("reserveurl") libkey = bookquery_isbn[query_systemid].get("libkey") if reserveurl or libkey: found = True bookstatus = ({ "systemid": query_systemid, "reserveurl": reserveurl, "libkey": libkey }) # If none of keys are found, raise BookNotFound. if found is False: raise BookNotFound except Exception as e: logger.info(e) raise BookNotFound else: logger.debug(f"bookstatus: {bookstatus}") return bookstatus
def add_favoilib(event=None, libinfo=None): """ Register new library at specified user. Parameters ---------- event: LINE event LINE event libinfo: dict New library information. Returns ------- status: str Return status string. Raises ------ UserNotFound Raises UserNotFound if user is not registered. DuplicateLibraryError Raises DuplicateLibraryError if new library is already registered. """ lib_doc = record.library status = "" userid = event.source.user_id if event else "testid" hashed_userid = sha256(userid.encode()).hexdigest() logger.debug(event) # test code # libinfo = {"formal": "会津大学附属図書館", "systemid": "Univ_Aizu"} if libinfo is None: libinfo = { "formal": "会津大学附属図書館", "systemid": "Univ_Aizu", "libid": "104688" } # confirmation of uniquness of the user if db.user.find(hashed_userid) is None: logger.info("user not found") raise UserNotFound user_doc = db.user.find(hashed_userid) favolib = user_doc["favolib"] logger.debug(f"registered favorite libraries: {favolib}") if libinfo["libid"] in list(map(lambda x: x["libid"], favolib)): raise DuplicateLibraryError # get info of one library from db libinfo = db.library.find(libinfo["libid"]) # make favorite library doc lib_doc["timestamp"] = int(time.time()) lib_doc["formal"] = libinfo["formal"] lib_doc["libid"] = libinfo["libid"] lib_doc["systemid"] = libinfo["systemid"] logger.debug(f"additional favorite library: {lib_doc}") favolib.append(lib_doc) user_doc["favolib"] = favolib db.user.set(hashed_userid, user_doc) # update favorite library logger.info(f"{favolib} is registared") status = "success" return status