main.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. # db connect and search
  41. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  42. table = db['users']
  43. result1 = table.find_one(userid=real_user_id)
  44. # 都存在db的話
  45. if result1:
  46. db.close()
  47. line_bot_api.reply_message(
  48. event.reply_token,
  49. TextSendMessage(text='很高興再見到您!'))
  50. # 建立全新使用者
  51. else:
  52. # create user account api
  53. url = 'https://nft-api-staging.joyso.io/api/v1/accounts'
  54. headers = {'Authorization': 'Basic bmZ0OmMxOTEzOWMzYjM3YjdjZWU3ZmY3OTFiZGU3NzdjZWNl'}
  55. # setup for temp use (unique id)
  56. rand_num = str(randrange(99999))
  57. user_id = event.source.user_id + rand_num
  58. data = 'uid=' + user_id
  59. r = requests.post(url=url, headers=headers, data=data)
  60. # extract the account address
  61. dict_str = json.loads(r.text)
  62. user_account = dict_str['account']
  63. user_address = user_account['address']
  64. # generate qr code from user id
  65. qr = qrcode.QRCode(
  66. version=1,
  67. box_size=10,
  68. border=5)
  69. qr.add_data(user_address)
  70. qr.make(fit=True)
  71. img_qr = qr.make_image(fill='black', back_color='white')
  72. filename = "/var/www/ArkCard-Linebot/ArkCard-web/qrcode/" + real_user_id + '.png'
  73. img_save = img_qr.save(filename)
  74. # add to db
  75. data = dict(userid=real_user_id, useraddress=user_address)
  76. table.insert(data)
  77. db.close()
  78. line_bot_api.reply_message(
  79. event.reply_token,
  80. TextSendMessage(text='歡迎加入好友'))
  81. db.close()
  82. # message handler
  83. @handler.add(MessageEvent, message=TextMessage)
  84. def message(event):
  85. if '我要發送' in event.message.text:
  86. button_template_message = ButtonsTemplate(
  87. title=' ',
  88. text='點擊並打開收藏的NFT,可以選擇想要發送的NFT給對方!',
  89. actions=[
  90. URITemplateAction(
  91. label='打開發送頁',
  92. uri='https://ark.cards/collect.html?' + event.source.user_id),])
  93. line_bot_api.reply_message(
  94. event.reply_token,
  95. TemplateSendMessage(
  96. alt_text="Receive",
  97. template=button_template_message))
  98. elif '我要接收' in event.message.text:
  99. button_template_message = ButtonsTemplate(
  100. title=' ',
  101. text='點擊並打開接收頁面,即可分享接收地址給對方!',
  102. actions=[
  103. URITemplateAction(
  104. label='打開接收頁',
  105. uri='https://ark.cards/qr-code.html?' + event.source.user_id),])
  106. line_bot_api.reply_message(
  107. event.reply_token,
  108. TemplateSendMessage(
  109. alt_text="Receive",
  110. template=button_template_message))
  111. elif 'NFT商店' in event.message.text:
  112. button_template_message = ButtonsTemplate(
  113. title=' ',
  114. text='點擊並打開NFT商品頁,就可以購買您所想要的NFT商品哦!',
  115. actions=[
  116. URITemplateAction(
  117. label='打開NFT商品頁',
  118. uri='https://ark.cards/shop.html?' + event.source.user_id),])
  119. line_bot_api.reply_message(
  120. event.reply_token,
  121. TemplateSendMessage(
  122. alt_text="Receive",
  123. template=button_template_message))
  124. elif 'NFT收藏' in event.message.text:
  125. button_template_message = ButtonsTemplate(
  126. title=' ',
  127. text='點擊並打開收藏的NFT,可以查看收到的NFT!',
  128. actions=[
  129. URITemplateAction(
  130. label='打開收藏頁',
  131. uri='https://ark.cards/collect.html?' + event.source.user_id), ])
  132. line_bot_api.reply_message(
  133. event.reply_token,
  134. TemplateSendMessage(
  135. alt_text="Receive",
  136. template=button_template_message))
  137. else:
  138. button_template_message = ButtonsTemplate(
  139. title=' ',
  140. text='更多的服務內容,歡迎請上我們的官網!',
  141. actions=[
  142. URITemplateAction(
  143. label='ArkCard的官網',
  144. uri='https://ark.cards'),])
  145. line_bot_api.reply_message(
  146. event.reply_token,
  147. TemplateSendMessage(
  148. alt_text="Receive",
  149. template=button_template_message))
  150. # nft collection api
  151. @app.get("/collection/{userid}")
  152. def collection(userid):
  153. # db connect
  154. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  155. table3 = db['nftdrops']
  156. table2 = db['nft']
  157. nftdrops = {}
  158. nft = {}
  159. nfts_all = {}
  160. i = 0
  161. j = 0
  162. if not table3.find_one(userid=userid) and not table2.find_one(userid=userid):
  163. db.close()
  164. return "error: user don't have any nft"
  165. else:
  166. results1 = table3.find(userid=userid)
  167. for item in results1:
  168. nft_id = item['nftid']
  169. nftdrops[i] = table2.find_one(id=nft_id)
  170. i += 1
  171. results2 = table2.find(userid=userid)
  172. for item in results2:
  173. nft[j] = item
  174. j += 1
  175. nfts_all[0] = nftdrops
  176. nfts_all[1] = nft
  177. return nfts_all
  178. db.close()
  179. db.close()
  180. # receive handler
  181. @app.get("/receive/{userid}")
  182. def receive(userid):
  183. # db connect
  184. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  185. table = db['users']
  186. table.find_one(userid=userid)
  187. if not table.find_one(userid=userid):
  188. db.close()
  189. return "ERROR: User Not Found"
  190. else:
  191. result = table.find_one(userid=userid)
  192. return {"userid": result['userid'], "useraddress": result['useraddress']}
  193. db.close()
  194. # send handler
  195. @app.post("/send")
  196. async def receive(userModel : models.TransactionNft):
  197. # db connect
  198. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  199. table = db['users']
  200. table2 = db['nft']
  201. table3 = db['nftdrops']
  202. # input and find userid
  203. nftid = userModel.nftid
  204. address = userModel.address
  205. result = table.find_one(useraddress=address)
  206. # first confirm if the user exist
  207. if not result:
  208. db.close()
  209. return {'msg': 'user address not found'}
  210. else:
  211. userid = result['userid']
  212. # update nft owner
  213. if table3.find_one(nftid=nftid):
  214. data = dict(nftid=nftid, userid=userid)
  215. table3.update(data, ['nftid'])
  216. db.close()
  217. elif table2.find_one(id=nftid):
  218. data = dict(id=nftid, userid=userid)
  219. table2.update(data, ['id'])
  220. db.close()
  221. else:
  222. db.close()
  223. return {'msg': 'nft not found'}
  224. db.close()
  225. return {'msg': 'OK'}
  226. # shop handler
  227. @app.get("/shop/{userid}")
  228. def shop(userid):
  229. # db connect
  230. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  231. sql = 'SELECT * FROM arkcard.nft WHERE userid IS NULL OR userid="" LIMIT 5'
  232. result = db.query(sql)
  233. rows = {}
  234. i = 0
  235. for row in result:
  236. rows[i] = row
  237. i += 1
  238. return rows
  239. db.close()
  240. @app.post("/buy")
  241. async def buy(userModel : models.BuyNft):
  242. # db connect
  243. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  244. table2 = db['nft']
  245. # input
  246. nftid = userModel.nftid
  247. userid = userModel.userid
  248. if not table2.find_one(id=nftid):
  249. db.close()
  250. print("error: nft not found")
  251. return "該NFT商品不存在!如果有疑問,請洽網站的服務信箱!"
  252. else:
  253. user_obj = table2.find_one(id=nftid)
  254. user_obj['userid'] = userid
  255. table2.update(dict(user_obj), ['id'])
  256. db.close()
  257. return "您已購買成功!"
  258. @app.post("/event")
  259. async def nftdrops(userModel : models.NftDrops):
  260. # db connect
  261. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/arkcard?charset=utf8mb4')
  262. table3 = db['nftdrops']
  263. # input對應
  264. eventid = '1'
  265. nftid = '101'
  266. nftid2 = '102'
  267. userid = userModel.userid
  268. email = userModel.email
  269. # 如果userid不在db, 寫入到一個空值nft
  270. if not table3.find_one(userid=userid):
  271. # 新增資料
  272. table3.insert(dict(eventid=eventid, nftid=nftid, userid=userid, email=email))
  273. table3.insert(dict(eventid=eventid, nftid=nftid2, userid=userid, email=email))
  274. db.close()
  275. return "新增成功"
  276. # 如果userid存在,回傳通知
  277. else:
  278. db.close()
  279. return "已有資料"
  280. if __name__ == '__main__':
  281. 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'))