line.py 11 KB

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