main.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import uvicorn
  2. import fastapi
  3. from fastapi.middleware.cors import CORSMiddleware
  4. from fastapi.responses import HTMLResponse
  5. from linebot import LineBotApi, WebhookHandler
  6. from linebot.models import (
  7. MessageEvent, TextMessage, TextSendMessage, FollowEvent, TemplateSendMessage, ButtonsTemplate, URITemplateAction,
  8. )
  9. import dataset
  10. import requests
  11. import json
  12. import qrcode
  13. from PIL import Image
  14. import base64, io
  15. from random import randrange
  16. import models
  17. app = fastapi.FastAPI()
  18. app.add_middleware(
  19. CORSMiddleware,
  20. allow_origins=['*'],
  21. allow_credentials=True,
  22. allow_methods=["*"],
  23. allow_headers=["*"],
  24. )
  25. # bot config
  26. line_bot_api = LineBotApi("SJT7VPT4RMQFLcS27jQBy3FcC24gtDrkcwJWZ5Xzqesr5T78LOKudHEJzt0k3b2S7n4KPwf27J7DVz2c8NQ4plSaaQylEeB1cYrfejaE/RPG/lCIQBYe4iBTzo26s4i2PcmT89837per/lTyvhVIKAdB04t89/1O/w1cDnyilFU=")
  27. handler = WebhookHandler("411ae3ef7e766739ed2c2c27b249d010")
  28. # callback event
  29. @app.post("/callback")
  30. async def callback(request: fastapi.Request):
  31. signature = request.headers['X-Line-Signature']
  32. body = await request.body()
  33. handler.handle(body.decode('utf-8'), signature)
  34. return 'OK'
  35. # follow event
  36. @handler.add(FollowEvent)
  37. def handle_follow(event):
  38. # get user id when follow
  39. real_user_id = event.source.user_id
  40. rand_num = str(randrange(99999))
  41. # db connect
  42. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  43. table = db['users']
  44. print(rand_num)
  45. user_id = event.source.user_id + rand_num
  46. result = table.find_one(userid=real_user_id)
  47. if result:
  48. line_bot_api.reply_message(
  49. event.reply_token,
  50. TextSendMessage(text='很高興再見到您!'))
  51. else:
  52. # create user account
  53. url = 'https://nft-api-staging.joyso.io/api/v1/accounts'
  54. headers = {'Authorization': 'Basic bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'}
  55. # setup for temp use (unique id)
  56. data = 'uid=' + user_id
  57. r = requests.post(url=url, headers=headers, data=data)
  58. # extract the account address
  59. dict_str = json.loads(r.text)
  60. user_account = dict_str['account']
  61. user_address = user_account['address']
  62. # generate qr code from user id
  63. qr = qrcode.QRCode(
  64. version=1,
  65. box_size=10,
  66. border=5)
  67. qr.add_data(user_address)
  68. qr.make(fit=True)
  69. img_qr = qr.make_image(fill='black', back_color='white')
  70. filename = "/var/www/ArkCard-Linebot/ArkCard-web/qrcode/" + real_user_id + '.png'
  71. img_save = img_qr.save(filename)
  72. # add to db
  73. result = "/qrcode/"+str(real_user_id)+'.png'
  74. data = dict(userid=real_user_id, useraddress=user_address, base=result)
  75. table.insert(data)
  76. line_bot_api.reply_message(
  77. event.reply_token,
  78. TextSendMessage(text='歡迎加入好友'))
  79. # message handler
  80. @handler.add(MessageEvent, message=TextMessage)
  81. def message(event):
  82. if '我要發送' in event.message.text:
  83. button_template_message = ButtonsTemplate(
  84. title=' ',
  85. text='點擊並打開收藏的NFT,可以選擇想要發送的NFT給對方!',
  86. actions=[
  87. URITemplateAction(
  88. label='打開發送頁',
  89. uri='https://ark.cards/collect.html?' + event.source.user_id),])
  90. line_bot_api.reply_message(
  91. event.reply_token,
  92. TemplateSendMessage(
  93. alt_text="Receive",
  94. template=button_template_message))
  95. elif '我要接收' in event.message.text:
  96. button_template_message = ButtonsTemplate(
  97. title=' ',
  98. text='點擊並打開接收頁面,即可分享接收地址給對方!',
  99. actions=[
  100. URITemplateAction(
  101. label='打開接收頁',
  102. uri='https://ark.cards/qr-code.html?' + event.source.user_id),])
  103. line_bot_api.reply_message(
  104. event.reply_token,
  105. TemplateSendMessage(
  106. alt_text="Receive",
  107. template=button_template_message))
  108. elif 'NFT商店' in event.message.text:
  109. button_template_message = ButtonsTemplate(
  110. title=' ',
  111. text='點擊並打開NFT商品頁,就可以購買您所想要的NFT商品哦!',
  112. actions=[
  113. URITemplateAction(
  114. label='打開NFT商品頁',
  115. uri='https://ark.cards/shop.html?' + event.source.user_id),])
  116. line_bot_api.reply_message(
  117. event.reply_token,
  118. TemplateSendMessage(
  119. alt_text="Receive",
  120. template=button_template_message))
  121. elif 'NFT收藏' in event.message.text:
  122. button_template_message = ButtonsTemplate(
  123. title=' ',
  124. text='點擊並打開收藏的NFT,可以查看收到的NFT!',
  125. actions=[
  126. URITemplateAction(
  127. label='打開收藏頁',
  128. uri='https://ark.cards/collect.html?' + event.source.user_id), ])
  129. line_bot_api.reply_message(
  130. event.reply_token,
  131. TemplateSendMessage(
  132. alt_text="Receive",
  133. template=button_template_message))
  134. else:
  135. button_template_message = ButtonsTemplate(
  136. title=' ',
  137. text='更多的服務內容,歡迎請上我們的官網!',
  138. actions=[
  139. URITemplateAction(
  140. label='ArkCard的官網',
  141. uri='https://ark.cards'),])
  142. line_bot_api.reply_message(
  143. event.reply_token,
  144. TemplateSendMessage(
  145. alt_text="Receive",
  146. template=button_template_message))
  147. # nft collection api
  148. @app.get("/collection/{userid}")
  149. def collection(userid):
  150. # db connect
  151. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  152. table1 = db['users']
  153. table2 = db['nft']
  154. if table1.find_one(userid=userid) and not table2.find_one(userid=userid):
  155. return "您尚未擁有NFT商品,歡迎前往NFT商店購買!"
  156. elif not table2.find_one(userid=userid):
  157. return "使用者不存在"
  158. else:
  159. xname = userid
  160. sql = 'SELECT a.* FROM nft a INNER JOIN (SELECT userid FROM users WHERE userid="' + xname + '") b ON b.userid = a.userid'
  161. result = db.query(sql)
  162. rows = {}
  163. i = 0
  164. for row in result:
  165. rows[i] = row
  166. i += 1
  167. return rows
  168. # receive handler
  169. @app.get("/receive/{userid}")
  170. def receive(userid):
  171. # db connect
  172. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  173. table = db['users']
  174. table.find_one(userid=userid)
  175. if not table.find_one(userid=userid):
  176. return "ERROR: User Not Found"
  177. else:
  178. result = table.find_one(userid=userid)
  179. return {"userid": result['userid'], "base": result['base'], "useraddress": result['useraddress']}
  180. # send handler
  181. @app.post("/send")
  182. async def receive(userModel : models.TransactionNft):
  183. # db connect
  184. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  185. table2 = db['nft']
  186. # input
  187. nftid = userModel.nftid
  188. address = userModel.address
  189. if not table2.find_one(id=nftid):
  190. print("error: nft not found")
  191. return {'msg': 'nft not found'}
  192. else:
  193. statement = 'SELECT userid FROM users WHERE useraddress ="'+address+'"'
  194. for row in db.query(statement):
  195. result = row['userid']
  196. user_obj = table2.find_one(id=nftid)
  197. user_obj['userid'] = result
  198. table2.update(dict(user_obj), ['id'])
  199. return {'msg': 'OK'}
  200. # shop handler
  201. @app.get("/shop/{userid}")
  202. def shop(userid):
  203. # db connect
  204. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  205. sql = 'SELECT * FROM arkcard.nft WHERE userid IS NULL OR userid="" LIMIT 5'
  206. result = db.query(sql)
  207. rows = {}
  208. i = 0
  209. for row in result:
  210. rows[i] = row
  211. i += 1
  212. return rows
  213. @app.post("/buy")
  214. async def buy(userModel : models.BuyNft):
  215. # db connect
  216. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  217. table2 = db['nft']
  218. # input
  219. nftid = userModel.nftid
  220. userid = userModel.userid
  221. if not table2.find_one(id=nftid):
  222. print("error: nft not found")
  223. return "該NFT商品不存在!如果有疑問,請洽網站的服務信箱!"
  224. else:
  225. user_obj = table2.find_one(id=nftid)
  226. user_obj['userid'] = userid
  227. table2.update(dict(user_obj), ['id'])
  228. return "您已購買成功!"
  229. if __name__ == '__main__':
  230. uvicorn.run("main:app", host="0.0.0.0", port=8228, reload=True,ssl_context=('/etc/letsencrypt/live/ark.cards/fullchain.pem', '/etc/letsencrypt/live/ark.cards/privkey.pem'))