CJYen 3 年之前
父節點
當前提交
0ac477ca0e
共有 3 個文件被更改,包括 408 次插入0 次删除
  1. 5 0
      app/api/api_v1/endpoints/config.py
  2. 385 0
      app/api/api_v1/endpoints/line.py
  3. 18 0
      app/api/api_v1/endpoints/models.py

+ 5 - 0
app/api/api_v1/endpoints/config.py

@@ -0,0 +1,5 @@
+from linebot import LineBotApi, WebhookHandler
+
+# bot config
+line_bot_api = LineBotApi("SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2PcmT89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
+handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")

+ 385 - 0
app/api/api_v1/endpoints/line.py

@@ -0,0 +1,385 @@
+import uvicorn
+import fastapi
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import HTMLResponse
+from linebot import LineBotApi, WebhookHandler
+from linebot.models import (
+    MessageEvent, TextMessage, TextSendMessage, FollowEvent, TemplateSendMessage, ButtonsTemplate, URITemplateAction,
+)
+import dataset
+import requests
+import json
+import qrcode
+# from PIL import Image
+# import base64, io
+from random import randrange
+import models
+import datetime as dt
+
+app = fastapi.FastAPI()
+
+app.add_middleware(
+    CORSMiddleware,
+    allow_origins=['*'],
+    allow_credentials=True,
+    allow_methods=["*"],
+    allow_headers=["*"],
+)
+
+# bot config
+line_bot_api = LineBotApi("SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2PcmT89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
+handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")
+
+# callback event
+@app.post("/callback")
+async def callback(request: fastapi.Request):
+    signature = request.headers['X-Line-Signature']
+    body = await request.body()
+    handler.handle(body.decode('utf-8'), signature)
+    return 'OK'
+
+# follow event
+@handler.add(FollowEvent)
+def handle_follow(event):
+    # get user id when follow
+    real_user_id = event.source.user_id
+
+    # db connect and search
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table = db['users']
+    result1 = table.find_one(userid=real_user_id)
+
+    # 都存在db的話
+    if result1:
+        db.close()
+        line_bot_api.reply_message(
+            event.reply_token,
+            TextSendMessage(text='很高興再見到您!'))
+
+    # 建立全新使用者
+    else:
+        # create user account api
+        url = 'https://nft-api-staging.joyso.io/api/v1/accounts'
+        headers = {'Authorization': 'Basic bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'}
+
+        # setup for temp use (unique id)
+        rand_num = str(randrange(99999))
+        user_id = event.source.user_id + rand_num
+        data = 'uid=' + user_id
+        r = requests.post(url=url, headers=headers, data=data)
+
+        # extract the account address
+        dict_str = json.loads(r.text)
+        user_account = dict_str['account']
+        user_address = user_account['address']
+
+        # generate qr code from user id
+        qr = qrcode.QRCode(
+            version=1,
+            box_size=10,
+            border=5)
+        qr.add_data(user_address)
+        qr.make(fit=True)
+        img_qr = qr.make_image(fill='black', back_color='white')
+        filename = "/var/www/ArkCard-Linebot/ArkCard-web/qrcode/" + real_user_id + '.png'
+        img_save = img_qr.save(filename)
+
+        # add to db
+        data = dict(userid=real_user_id, useraddress=user_address)
+        table.insert(data)
+
+        db.close()
+
+        line_bot_api.reply_message(
+            event.reply_token,
+            TextSendMessage(text='歡迎加入好友'))
+
+# message handler
+@handler.add(MessageEvent, message=TextMessage)
+def message(event):
+    if '我要發送' in event.message.text:
+        button_template_message = ButtonsTemplate(
+            title=' ',
+            text='點擊並打開收藏的NFT,可以選擇想要發送的NFT給對方!',
+            actions=[
+                URITemplateAction(
+                    label='打開發送頁',
+                    uri='https://ark.cards/collect.html?' + event.source.user_id),])
+        line_bot_api.reply_message(
+            event.reply_token,
+            TemplateSendMessage(
+                alt_text="Receive",
+                template=button_template_message))
+
+    elif '我要接收' in  event.message.text:
+        button_template_message = ButtonsTemplate(
+            title=' ',
+            text='點擊並打開接收頁面,即可分享接收地址給對方!',
+            actions=[
+                URITemplateAction(
+                    label='打開接收頁',
+                    uri='https://ark.cards/qr-code.html?' + event.source.user_id),])
+        line_bot_api.reply_message(
+            event.reply_token,
+            TemplateSendMessage(
+                alt_text="Receive",
+                template=button_template_message))
+
+    elif 'NFT商店' in event.message.text:
+        button_template_message = ButtonsTemplate(
+            title=' ',
+            text='點擊並打開NFT商品頁,就可以購買您所想要的NFT商品哦!',
+            actions=[
+                URITemplateAction(
+                    label='打開NFT商品頁',
+                    uri='https://ark.cards/shop.html?' + event.source.user_id),])
+        line_bot_api.reply_message(
+            event.reply_token,
+            TemplateSendMessage(
+                alt_text="Receive",
+                template=button_template_message))
+
+    elif 'NFT收藏' in event.message.text:
+        button_template_message = ButtonsTemplate(
+            title=' ',
+            text='點擊並打開收藏的NFT,可以查看收到的NFT!',
+            actions=[
+                URITemplateAction(
+                    label='打開收藏頁',
+                    uri='https://ark.cards/collect.html?' + event.source.user_id), ])
+        line_bot_api.reply_message(
+            event.reply_token,
+            TemplateSendMessage(
+                alt_text="Receive",
+                template=button_template_message))
+    else:
+        button_template_message = ButtonsTemplate(
+            title=' ',
+            text='更多的服務內容,歡迎請上我們的官網!',
+            actions=[
+                URITemplateAction(
+                    label='ArkCard的官網',
+                    uri='https://ark.cards'),])
+        line_bot_api.reply_message(
+            event.reply_token,
+            TemplateSendMessage(
+                alt_text="Receive",
+                template=button_template_message))
+
+# nft collection api
+@app.get("/collection/{userid}")
+def collection(userid):
+    # 連到ownership表單去找,並回傳json
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table1 = db['ownership']
+    nft = {}
+    i = 0
+    if not table1.find_one(userid=userid):
+        db.close()
+        return "error: user don't have any nft"
+    else:
+        results = db.query("SELECT nftid, amount FROM arkcard.ownership WHERE userid IN (SELECT userid FROM arkcard.ownership WHERE userid = '"+userid+"');")
+        for item in results:
+            nft[i] = item
+            i += 1
+        db.close()
+        return nft
+
+# receive handler
+@app.get("/receive/{userid}")
+def receive(userid):
+    # 確定要傳送的對象,到user去找到它
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table = db['users']
+
+    if not table.find_one(userid=userid):
+        db.close()
+        return "ERROR: User Not Found"
+    else:
+        result = table.find_one(userid=userid)
+        db.close()
+        return {"userid": result['userid'], "address": result['address']}
+
+# send handler
+@app.post("/send")
+async def receive(userModel : models.TransactionNft):
+    # 從網頁上選定好商品,在選定好數量後輸入收方地址;將把該商品轉到收方,並存下交易記錄
+    # 從ownership找到該userid的擁有人,再把擁有人userid改為收方,並在trans留下記錄
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table1 = db['users']
+    table2 = db['ownership']
+    table3 = db['transactions']
+
+    # find the userid from the selected nft
+    fromuser = userModel.fromuser
+    address = userModel.address
+    result1 = table1.find_one(address=address)
+    result2 = table1.find_one(userid=fromuser)
+    # 例:
+    # {
+    #   "fromuser": "a01",
+    #   "address": "0x4cd0ea8b1bdb5ab9249d96ccf3d8a0d3ada2bc76",
+    #   "dic": {"10":"2", "20":"3"}
+    # }
+    # 第一個為nftid, 第二個為amount,可以同時輸入多組nft給同一人
+    the_list = userModel.dic
+    fr_token = "from token"
+    _hash = "hash"
+
+    # confirm if the user exist
+    # 如果沒有這個接受者,回傳錯誤
+    if not result1:
+        db.close()
+        return {'msg': 'user not found'}
+    # 確認發送方的nft夠不夠發放
+    else:
+        for nftid, amount in the_list.items():
+            print("nft: "+nftid+",數量:"+ amount)
+            # 直接針對取到的值去做確認數量和更新表單,最後再記錄
+            # 確認sender的總數
+            result3 = db.query('SELECT SUM(amount) AS total FROM arkcard.ownership WHERE userid="' + fromuser + '" AND nftid ="' + nftid + '";')
+
+            # 把總數撈出來,存到total
+            for row in result3:
+                rows = row
+            total = rows['total']
+
+            # 如果總數不夠,就報錯回傳
+            if total == None or total < int(amount):
+                db.close()
+                return {"messge: NFT not enough"}
+
+            # 總數夠,在ownership刪去數量,並再新增ownership一筆
+            else:
+                # 今天到這,需要找出怎麼扣除總數的方式,目前找到的總數,會更新到資料欄位,導致原本才100個的,會被更新成499個,因為全加到一個
+                # 找接收者的userid
+                to_user = result1['userid']
+                old_address = result2['address']
+                print(total)
+                new_amount = total - int(amount)
+                # 更新原user總數
+                result4 = db.query('DELETE FROM arkcard.ownership WHERE userid="' + fromuser + '" AND nftid ="' + nftid + '";')
+                result5 = db.query('UPDATE arkcard.ownership SET amount = amount - "' + amount + '" WHERE userid = "' + fromuser + '" AND nftid = "' + nftid + '" LIMIT 1;')
+                new_data1 = dict(userid=fromuser, address=old_address, nftid=nftid, amount=new_amount)
+                table2.insert(new_data1)
+                # 增加新user數量
+                new_data2 = dict(userid=to_user, address=address, nftid=nftid, amount=int(amount))
+                table2.insert(new_data2)
+
+                # 在transactions記錄from和to, 以及時間等等
+                now = dt.datetime.now()
+                trans_data = dict(to_token=address, time=now, amount=int(amount), userid=fromuser, from_token=fr_token, hash=_hash)
+                table3.insert(trans_data)
+        db.close()
+        return {"messge: NFT 夠"}
+
+# shop handler
+@app.get("/shop")
+def shop():
+    # 為了顯示正確的nft網頁和數量,直接顯示nft表出來
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    result1 = db.query('SELECT nftid, launched, amount, type, title, context FROM arkcard.nft WHERE launched="y" AND nftid NOT IN(SELECT nftid FROM arkcard.nft_to_event);')
+    nfts = {}
+    i = 0
+    for row in result1:
+        nfts[i] = row
+        i += 1
+    return nfts
+    db.close()
+
+@app.post("/buy")
+async def buy(userModel : models.BuyNft):
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table1 = db['users']
+    table2 = db['ownership']
+    table3 = db['nft']
+    table4 = db['transactions']
+    shops = "shop"
+    hash = "hash"
+
+    # input
+    the_list = userModel.dic
+    address = userModel.address
+    # 例:
+    # {
+    #   "address": "d04",
+    #   "dic": {"1":"2","2":"3"}
+    # }
+
+    result1 = table1.find_one(address=address)
+
+    # 找不到該使用者就回報錯誤
+    if not result1:
+        db.close()
+        return "該用戶不存在!如果有疑問,請洽網站的服務信箱!"
+    else:
+        for nftid, amount in the_list.items():
+            # 先user找到該使用者的userid留著備用
+            userid = result1['userid']
+
+            # 更新到ownership
+            owner_data = [dict(userid=userid, address=address, nftid=nftid, amount=int(amount))]
+            table2.insert_many(owner_data)
+
+            # 更新nft數量
+            result3 = table3.find_one(nftid=nftid)
+            nft_total = result3['amount']
+            total = int(nft_total) - int(amount)
+            nft_data = dict(nftid=nftid, amount=int(total))
+            table3.update(nft_data, ['nftid'])
+
+            # 最後再來處理transactions
+            now = dt.datetime.now()
+            trans_data = dict(to_token=address, time=now, amount=int(amount), userid=userid, from_token=shops, hash=hash)
+            table4.insert(trans_data)
+        db.close()
+        return "您已購買成功!"
+
+@app.post("/event")
+async def nftdrops(userModel : models.NftDrops):
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    table1 = db['nft_drop_list']
+
+    # input
+    userid = userModel.userid
+    email = userModel.email
+
+    the_current_event = eventPeriod()
+
+    if the_current_event == 0:
+        return "目前沒有任何進行中的活動"
+    else:
+        # 再針對有上架的 event 填寫客戶到 nftdroplist
+        now = dt.datetime.now()
+        result1 = table1.find_one(userid=userid)
+        if not result1:
+            for key, item in the_current_event.items():
+                table1.insert(dict(eventid=item, userid=userid, email=email, time=now))
+            db.close()
+            return "完成加入"
+        else:
+            db.close()
+            return "該資料已存在"
+
+@app.post("/eventPeriod")
+def eventPeriod():
+    # db connect
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
+    # 設定event始終期間,與上架與否
+    table3 = db['event']
+    now = dt.datetime.now()
+    # 先去找 event 表,確認在期間之內
+    result = db.query("SELECT * FROM arkcard.event WHERE start < NOW() and NOW() < end and launched='yes';")
+    rows = {}
+    i = 0
+    for row in result:
+        rows[i] = row['eventid']
+        i += 1
+    return rows
+    db.close()

+ 18 - 0
app/api/api_v1/endpoints/models.py

@@ -0,0 +1,18 @@
+from pydantic import BaseModel
+
+class TransactionNft(BaseModel):
+    fromuser: str
+    address: str
+    dic: dict
+
+class BuyNft(BaseModel):
+    address: str
+    dic:dict
+
+class NftDrops(BaseModel):
+    userid: str
+    email: str
+
+class callBack(BaseModel):
+    type: str
+    data: dict