Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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)
Пример #5
0
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
Пример #6
0
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)
Пример #7
0
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
Пример #8
0
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
Пример #9
0
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))
Пример #10
0
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))
Пример #11
0
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
Пример #12
0
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
Пример #13
0
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))
Пример #14
0
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
Пример #15
0
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
Пример #16
0
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