line.py 11 KB

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