Advertisement
Guest User

Untitled

a guest
Jun 6th, 2018
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.08 KB | None | 0 0
  1. import re
  2. import datetime
  3. import util
  4. import settings
  5. import random
  6. import secrets
  7.  
  8. import tasks
  9.  
  10. from peewee import *
  11. from playhouse.postgres_ext import PostgresqlExtDatabase
  12.  
  13. # TODO - Redesign the schema
  14. # - TipBot grew into more than a tip bot quickly as features piled on
  15. # combined with a non-backwards compatible discord.py update and
  16. # the fact I never worked with python or peewee before this project.
  17. # So eventual schema redesign plans:
  18. # 1) Discord IDs are now integers. Every discord ID stored should become IntegerField
  19. # 2) Giveaway transactions should be further distinguished from normal TXs
  20. # after a giveaway is over, it's impossible to tell what transactions were part of the
  21. # giveaway. That's a mild design flaw
  22. # 3) Where applicable replace peewee default primary key with discord ID as primary key
  23. # many of our queries are written using discord IDs already.
  24. # e.g. user_id should be PrimaryKeyField on users table
  25. # 4) De-couple stats, accounts, etc. from users table.
  26. # (Make a one-to-many relationship between a users and stats/accounts table)
  27. # Why one-to-many instead of 1-1 for accounts? see point 8
  28. # 5) Foreign key relationships everywhere
  29. # 6) We only retrieve a DB connection 1 time, which isn't much of a problem for SQLite,
  30. # but perhaps a better practice would be to create and destroy connections as needed
  31. # which brings the next point:
  32. # 7) SQLite is fine for our purposes, but some operations would be much better if we
  33. # could do them atomically. (e.g. when multiple DB operations occur, if one fails
  34. # then everything rolls back). Not a problem with SQLite or peewee, per say, but
  35. # due to multithreading issues we use SQliteQueueDatabase which queues writes
  36. # synchronously and that breaks atomic transactions.
  37. # so....maybe eye a switch to MySQL or PostgreSQL
  38. # 8) Attach discord server ID to user accounts, stats, etc.
  39. # this will allow some important things for the future of NANO/BANANO bots
  40. # Mainly, allowing the bot to be used on multiple servers
  41. #
  42. # Of course, we need a way to migrate the old database into this re-design
  43.  
  44. # (Seconds) how long a user must wait in between messaging the bot
  45. LAST_MSG_TIME = 1
  46.  
  47. # How many messages consider a user rain eligible
  48. LAST_MSG_RAIN_COUNT = 5
  49. # (Seconds) How spaced out the messages must be
  50. LAST_MSG_RAIN_DELTA = 60
  51. # How many words messages must contain
  52. LAST_MSG_RAIN_WORDS = 3
  53.  
  54. # (Seconds) How long user must wait between tiprandom
  55. TIP_RANDOM_WAIT = 10
  56. # (Seconds) How long user mus wait between tipfavorites
  57. TIP_FAVORITES_WAIT = 150
  58.  
  59. db = PostgresqlExtDatabase(settings.database, user=settings.database_user, password=settings.database_password, host='localhost', port=5432)
  60.  
  61. logger = util.get_logger("db")
  62.  
  63. ### User Stuff
  64. @db.connection_context()
  65. def get_accounts():
  66. u = User.select()
  67. accts = []
  68. for a in u:
  69. accts.append(a.wallet_address)
  70. return accts
  71.  
  72. @db.connection_context()
  73. def get_user_by_id(user_id, user_name=None):
  74. try:
  75. user = User.get(user_id=str(user_id))
  76. if user_name is not None and user_name != user.user_name:
  77. User.update(user_name=user_name).where(User.id == user.id).execute()
  78. user.user_name = user_name
  79. return user
  80. except User.DoesNotExist:
  81. # logger.debug('user %s does not exist !', user_id)
  82. return None
  83.  
  84. @db.connection_context()
  85. def get_user_by_wallet_address(address):
  86. try:
  87. user = User.get(wallet_address=address)
  88. return user
  89. except User.DoesNotExist:
  90. # logger.debug('wallet %s does not exist !', address)
  91. return None
  92.  
  93. @db.connection_context()
  94. def user_exists(user_id):
  95. return User.select().where(User.user_id == user_id).count() > 0
  96.  
  97. @db.connection_context()
  98. def get_active_users(since_minutes):
  99. since_ts = datetime.datetime.now() - datetime.timedelta(minutes=since_minutes)
  100. users = User.select().where(User.last_msg > since_ts).order_by(User.user_id)
  101. return_ids = []
  102. for user in users:
  103. if user.last_msg_count >= LAST_MSG_RAIN_COUNT:
  104. if is_banned(user.user_id):
  105. continue
  106. return_ids.append(user.user_id)
  107. return return_ids
  108.  
  109. @db.connection_context()
  110. def get_address(user_id):
  111. logger.info('getting wallet address for user %d ...', user_id)
  112. user = get_user_by_id(user_id)
  113. if user is None:
  114. return None
  115. else:
  116. return user.wallet_address
  117.  
  118. @db.connection_context()
  119. def get_top_users(count):
  120. users = User.select().where((User.tipped_amount > 0) & (User.stats_ban == False)).order_by(User.tipped_amount.desc()).limit(count)
  121. return_data = []
  122. for idx, user in enumerate(users):
  123. return_data.append({'index': idx + 1, 'name': user.user_name, 'amount': user.tipped_amount})
  124. return return_data
  125.  
  126. @db.connection_context()
  127. def get_giveaway_winners(count):
  128. winners = Giveaway.select().where((Giveaway.active == False) & (Giveaway.winner_id.is_null(False))).order_by(Giveaway.end_time.desc()).limit(count)
  129. return_data = []
  130. for idx, winner in enumerate(winners):
  131. user = get_user_by_id(winner.winner_id)
  132. return_data.append({'index': idx + 1, 'name': user.user_name, 'amount': winner.amount + winner.tip_amount})
  133. return return_data
  134.  
  135. @db.connection_context()
  136. def get_tip_stats(user_id):
  137. user_id = str(user_id)
  138. user = get_user_by_id(user_id)
  139. if user is None:
  140. return None
  141. rank = User.select().where((User.tipped_amount > user.tipped_amount) & (User.stats_ban == False)).count() + 1
  142. if not user.stats_ban:
  143. tipped_amount = user.tipped_amount
  144. tip_count = user.tip_count
  145. top_tip = user.top_tip
  146. else:
  147. tipped_amount = 0
  148. tip_count = 0
  149. top_tip = 0
  150. rank = -1
  151. if tip_count == 0:
  152. average = 0
  153. else:
  154. average = tipped_amount / tip_count
  155. return {'rank':rank, 'total':tipped_amount, 'average':average,'top':float(top_tip) / 1000000}
  156.  
  157. # Update tip stats
  158. @db.connection_context()
  159. def update_tip_stats(user, tip, rain=False, giveaway=False):
  160. (User.update(
  161. tipped_amount=(User.tipped_amount + (tip / 1000000)),
  162. tip_count = User.tip_count + 1
  163. ).where(User.id == user.id)
  164. ).execute()
  165. # Update all time tip if necessary
  166. if tip > int(float(user.top_tip)):
  167. (User.update(
  168. top_tip = tip,
  169. top_tip_ts = datetime.datetime.now()
  170. ).where(User.id == user.id)
  171. ).execute()
  172. # Update monthly tip if necessary
  173. if user.top_tip_month_ts.month != datetime.datetime.now().month or tip > int(float(user.top_tip_month)):
  174. (User.update(
  175. top_tip_month = tip,
  176. top_tip_month_ts = datetime.datetime.now()
  177. ).where(User.id == user.id)
  178. ).execute()
  179. # Update 24H tip if necessary
  180. delta = datetime.datetime.now() - user.top_tip_day_ts
  181. if delta.total_seconds() > 86400 or tip > int(float(user.top_tip_day)):
  182. (User.update(
  183. top_tip_day = tip,
  184. top_tip_day_ts = datetime.datetime.now()
  185. ).where(User.id == user.id)
  186. ).execute()
  187. # Update rain or giveaway stats
  188. if rain:
  189. (User.update(
  190. rain_amount = User.rain_amount + (tip / 1000000)
  191. )
  192. .where(User.id == user.id)
  193. ).execute()
  194. elif giveaway:
  195. (User.update(
  196. giveaway_amount = User.giveaway_amount + (tip / 1000000)
  197. )
  198. .where(User.id == user.id)
  199. ).execute()
  200.  
  201. @db.connection_context()
  202. def update_tip_total(user_id, new_total):
  203. user_id = str(user_id)
  204. User.update(tipped_amount = new_total).where(User.user_id == user_id).execute()
  205. return
  206.  
  207. @db.connection_context()
  208. def update_tip_count(user_id, new_count):
  209. user_id = str(user_id)
  210. User.update(tip_count = new_count).where(User.user_id == user_id).execute()
  211. return
  212.  
  213. @db.connection_context()
  214. def update_pending(user_id, send=0, receive=0):
  215. user_id=str(user_id)
  216. return (User.update(
  217. pending_send = (User.pending_send + send),
  218. pending_receive = (User.pending_receive + receive)
  219. ).where(User.user_id == user_id)
  220. ).execute()
  221.  
  222. @db.connection_context()
  223. def create_user(user_id, user_name, wallet_address):
  224. user_id=str(user_id)
  225. user = User(user_id=user_id,
  226. user_name=user_name,
  227. wallet_address=wallet_address,
  228. )
  229. user.save()
  230. return user
  231.  
  232. ### Transaction Stuff
  233. @db.connection_context()
  234. def create_transaction(src_usr, uuid, to_addr, amt, target_id=None, giveaway_id=0):
  235. # Increment amount of giveaway TX if user has already donated to giveaway
  236. if giveaway_id != 0:
  237. try:
  238. giveawayTx = (Transaction.select()
  239. .where(
  240. (Transaction.source_address == src_usr.wallet_address) &
  241. (Transaction.giveawayid == giveaway_id)
  242. )
  243. ).get()
  244. update = (Transaction.update(amount = Transaction.amount.cast('integer') + amt)
  245. .where(Transaction.id == giveawayTx.id)
  246. ).execute()
  247. if update > 0:
  248. update_pending(src_usr.user_id, send=amt)
  249. return
  250. except Transaction.DoesNotExist:
  251. pass
  252.  
  253. tx = Transaction(uid=uuid,
  254. source_address=src_usr.wallet_address,
  255. to_address=to_addr,
  256. amount=amt,
  257. giveawayid=giveaway_id
  258. )
  259. tx.save()
  260. update_pending(src_usr.user_id, send=amt)
  261. if target_id is not None:
  262. update_pending(target_id, receive=amt)
  263. if tx.giveawayid == 0:
  264. process_transaction(tx)
  265. return tx
  266.  
  267. def process_transaction(tx):
  268. tasks.send_transaction.delay(tx)
  269.  
  270. @db.connection_context()
  271. def update_last_withdraw(user_id):
  272. user_id = str(user_id)
  273. User.update(last_withdraw=datetime.datetime.now()).where(User.user_id == user_id).execute()
  274.  
  275. @db.connection_context()
  276. def get_last_withdraw_delta(user_id):
  277. user_id = str(user_id)
  278. try:
  279. user = User.select(User.last_withdraw).where(User.user_id == user_id).get()
  280. delta = (datetime.datetime.now() - user.last_withdraw).total_seconds()
  281. return delta
  282. except User.DoesNotExist:
  283. return None
  284.  
  285. @db.connection_context()
  286. def get_unprocessed_transactions():
  287. # We don't simply return the txs list cuz that causes issues with database locks in the thread
  288. txs = Transaction.select().where((Transaction.processed == False) & (Transaction.giveawayid == 0)).order_by(Transaction.created)
  289. return_data = []
  290. for tx in txs:
  291. return_data.append({'uid':tx.uid,'source_address':tx.source_address,'to_address':tx.to_address,'amount':tx.amount,'attempts':tx.attempts})
  292. return return_data
  293.  
  294. @db.connection_context()
  295. def process_giveaway_transactions(giveaway_id, winner_user_id):
  296. txs = Transaction.select().where(Transaction.giveawayid == giveaway_id)
  297. winner = get_user_by_id(winner_user_id)
  298. pending_receive = 0
  299. for tx in txs:
  300. pending_receive += int(tx.amount)
  301. process_transaction(tx)
  302. update_pending(winner_user_id, receive=pending_receive)
  303. (Transaction.update(
  304. to_address = winner.wallet_address,
  305. giveawayid = 0
  306. ).where(
  307. (Transaction.giveawayid == giveaway_id)
  308. )).execute()
  309.  
  310. # Start Giveaway
  311. @db.connection_context()
  312. def start_giveaway(user_id, user_name, amount, end_time, channel, entry_fee = 0):
  313. user_id=str(user_id)
  314. channel=str(channel)
  315. giveaway = Giveaway(started_by=user_id,
  316. started_by_name=user_name,
  317. active=True,
  318. amount = amount,
  319. tip_amount = 0,
  320. end_time=end_time,
  321. channel_id = channel,
  322. winner_id = None,
  323. entry_fee = entry_fee
  324. )
  325. giveaway.save()
  326. # Delete contestants not meeting fee criteria
  327. deleted = []
  328. if entry_fee > 0:
  329. entries = Contestant.select()
  330. for c in entries:
  331. donated = get_tipgiveaway_contributions(c.user_id)
  332. if entry_fee > donated:
  333. c.delete_instance()
  334. deleted.append(c.user_id)
  335. tip_amt = update_giveaway_transactions(giveaway.id)
  336. giveaway.tip_amount = tip_amt
  337. giveaway.save()
  338. return (giveaway, deleted)
  339.  
  340. @db.connection_context()
  341. def get_giveaway():
  342. try:
  343. giveaway = Giveaway.get(active=True)
  344. return giveaway
  345. except:
  346. return None
  347.  
  348. @db.connection_context()
  349. def update_giveaway_transactions(giveawayid):
  350. tip_sum = 0
  351. txs = Transaction.select().where(Transaction.giveawayid == -1)
  352. for tx in txs:
  353. tip_sum += int(tx.amount)
  354. (Transaction.update(
  355. giveawayid = giveawayid
  356. ).where(
  357. (Transaction.giveawayid == -1)
  358. )).execute()
  359.  
  360. return float(tip_sum)/ 1000000
  361.  
  362. @db.connection_context()
  363. def add_tip_to_giveaway(amount):
  364. giveawayupdt = (Giveaway
  365. .update(
  366. tip_amount = (Giveaway.tip_amount + amount)
  367. ).where(Giveaway.active == True)
  368. ).execute()
  369.  
  370. @db.connection_context()
  371. def get_tipgiveaway_sum():
  372. tip_sum = 0
  373. txs = Transaction.select().where(Transaction.giveawayid == -1)
  374. for tx in txs:
  375. tip_sum += int(tx.amount)
  376. return tip_sum
  377.  
  378. # Get tipgiveaway contributions
  379. @db.connection_context()
  380. def get_tipgiveaway_contributions(user_id, giveawayid=-1):
  381. tip_sum = 0
  382. user = get_user_by_id(user_id)
  383. txs = Transaction.select().where((Transaction.giveawayid == giveawayid) & (Transaction.source_address == user.wallet_address))
  384. for tx in txs:
  385. tip_sum += int(tx.amount)
  386. return tip_sum
  387.  
  388. @db.connection_context()
  389. def is_banned(user_id):
  390. user_id=str(user_id)
  391. banned = BannedUser.select().where(BannedUser.user_id == user_id).count()
  392. return banned > 0
  393.  
  394. @db.connection_context()
  395. def ban_user(user_id):
  396. user_id = str(user_id)
  397. already_banned = is_banned(user_id)
  398. if already_banned > 0:
  399. return False
  400. ban = BannedUser(user_id=user_id)
  401. ban.save()
  402. return True
  403.  
  404. @db.connection_context()
  405. def statsban_user(user_id):
  406. user_id = str(user_id)
  407. banned = User.update(stats_ban = True).where(User.user_id == user_id).execute()
  408. return banned > 0
  409.  
  410. @db.connection_context()
  411. def unban_user(user_id):
  412. user_id = str(user_id)
  413. deleted = BannedUser.delete().where(BannedUser.user_id == user_id).execute()
  414. return deleted > 0
  415.  
  416. @db.connection_context()
  417. def statsunban_user(user_id):
  418. user_id = str(user_id)
  419. unbanned = User.update(stats_ban = False).where(User.user_id == user_id).execute()
  420. return unbanned > 0
  421.  
  422. @db.connection_context()
  423. def get_banned():
  424. banned = BannedUser.select(BannedUser.user_id)
  425. users = User.select(User.user_name).where(User.user_id.in_(banned))
  426. if users.count() == 0:
  427. return "```Nobody Banned```"
  428. ret = "```"
  429. for idx,user in enumerate(users):
  430. ret += "{0}: {1}\n".format(idx+1,user.user_name)
  431. ret += "```"
  432. return ret
  433.  
  434. @db.connection_context()
  435. def get_statsbanned():
  436. statsbanned = User.select().where(User.stats_ban == True)
  437. if statsbanned.count() == 0:
  438. return "```No stats bans```"
  439. ret = "```"
  440. for idx,user in enumerate(statsbanned):
  441. ret += "{0}: {1}\n".format(idx+1,user.user_name)
  442. ret += "```"
  443. return ret
  444.  
  445. @db.connection_context()
  446. def is_frozen(user_id):
  447. return FrozenUser.select().where(FrozenUser.user_id == user_id).count() > 0
  448.  
  449. @db.connection_context()
  450. def freeze(user):
  451. if not is_frozen(user.id):
  452. fu = FrozenUser(user_id=user.id, user_name=user.name)
  453. saved = fu.save()
  454. return saved > 0
  455. return False
  456.  
  457. @db.connection_context()
  458. def unfreeze(user_id):
  459. if not is_frozen(user_id):
  460. return False
  461. return FrozenUser.delete().where(FrozenUser.user_id==user_id).execute() > 0
  462.  
  463. @db.connection_context()
  464. def frozen():
  465. frozen = FrozenUser.select()
  466. if frozen.count() == 0:
  467. return "```Nobody Frozen```"
  468. ret = "```"
  469. for idx, fu in enumerate(frozen):
  470. ret += "{0}: {1}\n".format(idx+1, fu.user_name)
  471. ret += "```"
  472. return ret
  473.  
  474. # Returns winning user
  475. @db.connection_context()
  476. def finish_giveaway():
  477. contestants = Contestant.select(Contestant.user_id).order_by(Contestant.user_id)
  478. contestant_ids = []
  479. for c in contestants:
  480. contestant_ids.append(c.user_id)
  481. sysrand = random.SystemRandom()
  482. sysrand.shuffle(contestant_ids)
  483. offset = secrets.randbelow(len(contestant_ids))
  484. winner = get_user_by_id(contestant_ids[offset])
  485. Contestant.delete().execute()
  486. giveaway = Giveaway.get(active=True)
  487. giveaway.active=False
  488. giveaway.winner_id = winner.user_id
  489. giveaway.save()
  490. process_giveaway_transactions(giveaway.id, winner.user_id)
  491. return giveaway
  492.  
  493. # Returns True is contestant added, False if contestant already exists
  494. @db.connection_context()
  495. def add_contestant(user_id):
  496. user_id=str(user_id)
  497. exists = Contestant.select().where(Contestant.user_id == user_id).count() > 0
  498. if exists:
  499. return False
  500. contestant = Contestant(user_id=user_id,banned=False)
  501. contestant.save()
  502. return True
  503.  
  504. @db.connection_context()
  505. def get_ticket_status(user_id):
  506. user_id = str(user_id)
  507. try:
  508. giveaway = Giveaway.select().where(Giveaway.active==True).get()
  509. if contestant_exists(user_id):
  510. return "You are already entered into the giveaway!"
  511. fee = giveaway.entry_fee
  512. contributions = get_tipgiveaway_contributions(user_id, giveawayid=giveaway.id)
  513. cost = fee - contributions
  514. return_str = ("You do not have a ticket to the current giveaway!\n" +
  515. "Giveaway fee: {0}\n" +
  516. "Your donations: {1}\n" +
  517. "Your ticket cost: {2}\n\n" +
  518. "You may enter using `{3}ticket {2}`").format(fee, contributions, cost, settings.command_prefix)
  519. return return_str
  520. except Giveaway.DoesNotExist:
  521. contributions = get_tipgiveaway_contributions(user_id)
  522. return ("There is no active giveaway.\n" +
  523. "So far you've contributed {0} naneroo towards the next one.\n" +
  524. "I'll automatically enter you into the next giveaway if the fee is <= {0} naneroo").format(contributions)
  525.  
  526. @db.connection_context()
  527. def contestant_exists(user_id):
  528. user_id = str(user_id)
  529. c = Contestant.select().where(Contestant.user_id == user_id).count()
  530. return c > 0
  531.  
  532. @db.connection_context()
  533. def is_active_giveaway():
  534. giveaway = Giveaway.select().where(Giveaway.active==True).count()
  535. if giveaway > 0:
  536. return True
  537. return False
  538.  
  539. # Gets giveaway stats
  540. @db.connection_context()
  541. def get_giveaway_stats():
  542. try:
  543. giveaway = Giveaway.get(active=True)
  544. entries = Contestant.select().count()
  545. return {"amount":giveaway.amount + giveaway.tip_amount, "started_by":giveaway.started_by_name, "entries":entries, "end":giveaway.end_time,"fee":giveaway.entry_fee}
  546. except Giveaway.DoesNotExist:
  547. return None
  548.  
  549. @db.connection_context()
  550. def inc_tx_attempts(uid):
  551. tx = Transaction.get(uid = uid)
  552. if tx is not None:
  553. tx.attempts += 1
  554. tx.save()
  555. return
  556.  
  557. @db.connection_context()
  558. def update_top_tips(user_id, month=0,day=0,alltime=0):
  559. return (User.update(top_tip = User.top_tip + alltime,
  560. top_tip_month = User.top_tip_month + month,
  561. top_tip_day = User.top_tip_day + day
  562. ).where(User.user_id == user_id)).execute()
  563.  
  564. @db.connection_context()
  565. def get_top_tips():
  566. dt = datetime.datetime.now()
  567. past_dt = dt - datetime.timedelta(days=1) # Date 24H ago
  568. month_str = dt.strftime("%B")
  569. month_num = "{0:02d}".format(dt.month) # Sqlite uses 2 digit month (with leading 0)
  570. amount = fn.MAX(User.top_tip).alias('amount')
  571. amount_day = fn.MAX(User.top_tip_day).alias('amount')
  572. amount_month = fn.MAX(User.top_tip_month).alias('amount')
  573. top_24h = User.select(amount_day, User.user_name).where((User.top_tip_day_ts > past_dt) & (User.stats_ban == False)).order_by(User.top_tip_day_ts).limit(1)
  574. top_month = User.select(amount_month, User.user_name).where((fn.strftime("%m", User.top_tip_month_ts) == month_num) & (User.stats_ban == False)).order_by(User.top_tip_month_ts).limit(1)
  575. top_at = User.select(amount, User.user_name).where(User.stats_ban == False).order_by(User.top_tip_ts).limit(1)
  576. # Formatted output
  577. user24h = None
  578. monthuser = None
  579. atuser = None
  580.  
  581. for top in top_24h:
  582. user24h = top.user_name
  583. amount24h = float(top.amount) / 1000000
  584. for top in top_month:
  585. monthuser = top.user_name
  586. monthamount = float(top.amount) / 1000000
  587. for top in top_at:
  588. atuser = top.user_name
  589. atamount = float(top.amount) / 1000000
  590.  
  591. if user24h is None and monthuser is None and atuser is None:
  592. return "```No Tips Found```"
  593.  
  594. result = ""
  595. if user24h is not None:
  596. result += "Biggest tip in the last 24 hours:```{0:.6f} NANO by {1}```".format(amount24h, user24h)
  597. if monthuser is not None:
  598. result += "Biggest tip in {0}:```{1:.6f} NANO by {2}```".format(month_str, monthamount, monthuser)
  599. if atuser is not None:
  600. result += "Biggest tip of all time:```{0:.6f} NANO by {1}```".format(atamount, atuser)
  601.  
  602. return result
  603.  
  604. # Marks TX as processed and adds the block hash
  605. @db.connection_context()
  606. def mark_transaction_processed(uuid, amt, source_id, tranid, target_id=None):
  607. tu = (Transaction.update(
  608. sent = True,
  609. processed = True,
  610. tran_id = tranid
  611. ).where(
  612. (Transaction.uid == uuid) &
  613. (Transaction.processed == False)
  614. )).execute()
  615. if tu > 0:
  616. update_pending(source_id,send=amt)
  617. if target_id is not None:
  618. update_pending(target_id, receive=amt)
  619.  
  620. # Return false if last message was < LAST_MSG_TIME
  621. # If > LAST_MSG_TIME, return True and update the user
  622. # Also return true, if user does not have a tip bot acct yet
  623. @db.connection_context()
  624. def last_msg_check(user_id, content, is_private):
  625. user = get_user_by_id(user_id)
  626. if user is None:
  627. return True
  628. # Get difference in seconds between now and last msg
  629. since_last_msg_s = (datetime.datetime.now() - user.last_msg).total_seconds()
  630. if since_last_msg_s < LAST_MSG_TIME:
  631. return False
  632. else:
  633. update_last_msg(user, since_last_msg_s, content, is_private)
  634. return True
  635.  
  636. @db.connection_context()
  637. def update_last_msg(user, delta, content, is_private):
  638. content_adjusted = unicode_strip(content)
  639. words = content_adjusted.split(' ')
  640. adjusted_count = 0
  641. prev_len = 0
  642. for word in words:
  643. word = word.strip()
  644. cur_len = len(word)
  645. if cur_len > 0:
  646. if word.startswith(":") and word.endswith(":"):
  647. continue
  648. if prev_len == 0:
  649. prev_len = cur_len
  650. adjusted_count += 1
  651. else:
  652. res = prev_len % cur_len
  653. prev_len = cur_len
  654. if res != 0:
  655. adjusted_count += 1
  656. if adjusted_count >= LAST_MSG_RAIN_WORDS:
  657. break
  658. if delta >= 1800:
  659. user.last_msg_count = 0
  660. if adjusted_count >= LAST_MSG_RAIN_WORDS and not is_private and (datetime.datetime.now() - user.last_msg_rain).total_seconds() > LAST_MSG_RAIN_DELTA:
  661. user.last_msg_count += 1
  662. user.last_msg_rain = datetime.datetime.now()
  663. user.last_msg=datetime.datetime.now()
  664. (User.update(
  665. last_msg_count = user.last_msg_count,
  666. last_msg_rain = user.last_msg_rain,
  667. last_msg = user.last_msg
  668. ).where(User.user_id == user.user_id)
  669. ).execute()
  670. return
  671.  
  672. @db.connection_context()
  673. def unicode_strip(content):
  674. pattern = re.compile("["
  675. u"\U0001F600-\U0001F64F"
  676. u"\U0001F300-\U0001F5FF"
  677. u"\U0001F1E0-\U0001F1FF"
  678. u"\U00002702-\U000027B0"
  679. u"\U000024C2-\U0001F251"
  680. "]+", flags=re.UNICODE)
  681. return pattern.sub(r'',content)
  682.  
  683. @db.connection_context()
  684. def mark_user_active(user):
  685. if user is None:
  686. return
  687. if LAST_MSG_RAIN_COUNT > user.last_msg_count:
  688. (User.update(
  689. last_msg_count = LAST_MSG_RAIN_COUNT
  690. ).where(User.user_id == user.user_id)
  691. ).execute()
  692.  
  693. ## Favorites
  694.  
  695. # Return true if favorite added
  696. @db.connection_context()
  697. def add_favorite(user_id, favorite_id):
  698. user_id=str(user_id)
  699. favorite_id=str(favorite_id)
  700. if not user_exists(favorite_id):
  701. return False
  702. count = UserFavorite.select().where(UserFavorite.user_id == user_id).count()
  703. # Identifier makes it easy for user to remove their favorite via DM
  704. if count == 0:
  705. identifier = 1
  706. else:
  707. identifier = count + 1
  708. exists = UserFavorite.select().where((UserFavorite.user_id == user_id) & (UserFavorite.favorite_id == favorite_id)).count()
  709. if exists == 0:
  710. fav = UserFavorite(user_id=user_id,favorite_id=favorite_id,identifier=identifier)
  711. fav.save()
  712. return True
  713. return False
  714.  
  715. # Returns true if favorite deleted
  716. @db.connection_context()
  717. def remove_favorite(user_id, favorite_id=None,identifier=None):
  718.  
  719. if favorite_id is None and identifier is None:
  720. return False
  721. user_id=str(user_id)
  722. if favorite_id is not None:
  723. favorite_id = str(favorite_id)
  724. return UserFavorite.delete().where((UserFavorite.user_id == user_id) & (UserFavorite.favorite_id == favorite_id)).execute() > 0
  725. elif identifier is not None:
  726. return UserFavorite.delete().where((UserFavorite.user_id == user_id) & (UserFavorite.identifier == identifier)).execute() > 0
  727.  
  728. # Returns list of favorites for user ID
  729. @db.connection_context()
  730. def get_favorites_list(user_id):
  731. user_id = str(user_id)
  732. favorites = UserFavorite.select().where(UserFavorite.user_id==user_id).order_by(UserFavorite.identifier)
  733. idx = 1
  734. # Normalize identifiers
  735. for fav in favorites:
  736. fav.identifier = idx
  737. UserFavorite.update(identifier=idx).where((UserFavorite.user_id==user_id) & (UserFavorite.favorite_id == fav.favorite_id)).execute()
  738. idx += 1
  739. return_data = []
  740. for fav in favorites:
  741. return_data.append({'user_id':fav.favorite_id,'id': fav.identifier})
  742. return return_data
  743.  
  744. # Returns list of muted for user id
  745. @db.connection_context()
  746. def get_muted(user_id):
  747. user_id = str(user_id)
  748. muted = MutedList.select().where(MutedList.user_id==user_id)
  749. return_data = []
  750. for m in muted:
  751. return_data.append({'name':m.muted_name, 'id': m.muted_id})
  752. return return_data
  753.  
  754. # Return True if muted
  755. @db.connection_context()
  756. def muted(source_user, target_user):
  757. source_user = str(source_user)
  758. target_user = str(target_user)
  759. return MutedList.select().where((MutedList.user_id==source_user) & (MutedList.muted_id==target_user)).count() > 0
  760.  
  761. # Return false if already muted, True if muted
  762. @db.connection_context()
  763. def mute(source_user, target_user, target_name):
  764. if muted(source_user, target_user):
  765. return False
  766. source_user = str(source_user)
  767. target_user = str(target_user)
  768. mute = MutedList(user_id=source_user,muted_id=target_user,muted_name=target_name)
  769. mute.save()
  770. return True
  771.  
  772. # Return a number > 0 if user was unmuted
  773. @db.connection_context()
  774. def unmute(source_user, target_user):
  775. source_user = str(source_user)
  776. target_user = str(target_user)
  777. return MutedList.delete().where((MutedList.user_id==source_user) & (MutedList.muted_id==target_user)).execute()
  778.  
  779.  
  780. # Returns seconds user must wait to tiprandom again
  781. @db.connection_context()
  782. def tiprandom_check(user):
  783. delta = (datetime.datetime.now() - user.last_random).total_seconds()
  784. if TIP_RANDOM_WAIT > delta:
  785. return (TIP_RANDOM_WAIT - delta)
  786. else:
  787. User.update(last_random=datetime.datetime.now()).where(User.user_id == user.user_id).execute()
  788. return 0
  789.  
  790. # Returns seconds user must wait to tipfavorites again
  791. @db.connection_context()
  792. def tipfavorites_check(user):
  793. delta = (datetime.datetime.now() -user.last_favorites).total_seconds()
  794. if TIP_FAVORITES_WAIT > delta:
  795. return (TIP_FAVORITES_WAIT - delta)
  796. else:
  797. User.update(last_favorites=datetime.datetime.now()).where(User.user_id == user.user_id).execute()
  798. return 0
  799.  
  800. # Base Model
  801. class BaseModel(Model):
  802. class Meta:
  803. database = db
  804. # User table
  805. class User(BaseModel):
  806. user_id = CharField(unique=True)
  807. user_name = CharField()
  808. wallet_address = CharField(unique=True)
  809. tipped_amount = FloatField(default=0.0)
  810. pending_receive = IntegerField(default=0)
  811. pending_send = IntegerField(default=0)
  812. tip_count = IntegerField(default=0)
  813. created = DateTimeField(default=datetime.datetime.now())
  814. last_msg = DateTimeField(default=datetime.datetime.now())
  815. last_msg_rain = DateTimeField(default=datetime.datetime.now())
  816. last_msg_count = IntegerField(default=0)
  817. top_tip = IntegerField(default=0)
  818. top_tip_ts = DateTimeField(default=datetime.datetime.now())
  819. top_tip_month = IntegerField(default=0)
  820. top_tip_month_ts = DateTimeField(default=datetime.datetime.now())
  821. top_tip_day = IntegerField(default=0)
  822. top_tip_day_ts = DateTimeField(default=datetime.datetime.now())
  823. last_withdraw = DateTimeField(default=datetime.datetime.now())
  824. stats_ban = BooleanField(default=False)
  825. rain_amount = FloatField(default=0.0,)
  826. giveaway_amount = FloatField(default=0.0)
  827. last_random = DateTimeField(default=datetime.datetime.now())
  828. last_favorites = DateTimeField(default=datetime.datetime.now())
  829.  
  830. # Transaction table, keep trac of sends to process
  831. class Transaction(BaseModel):
  832. uid = CharField(unique=True)
  833. source_address = CharField()
  834. to_address = CharField(null = True)
  835. amount = CharField()
  836. sent = BooleanField(default=False)
  837. processed = BooleanField(default=False)
  838. created = DateTimeField(default=datetime.datetime.now())
  839. tran_id = CharField(default='', null=True)
  840. attempts = IntegerField(default=0)
  841. giveawayid = IntegerField(null = True)
  842.  
  843. # Giveaway table, keep track of current giveaway
  844. class Giveaway(BaseModel):
  845. started_by = CharField() # User ID
  846. started_by_name = CharField() # User Name
  847. active = BooleanField()
  848. amount = FloatField()
  849. tip_amount = FloatField()
  850. end_time = DateTimeField()
  851. channel_id = CharField() # The channel to post the results
  852. winner_id = CharField(null = True)
  853. entry_fee = IntegerField()
  854.  
  855. # Giveaway Entrants
  856. class Contestant(BaseModel):
  857. user_id = CharField(unique=True)
  858. banned = BooleanField()
  859.  
  860. # Banned List
  861. class BannedUser(BaseModel):
  862. user_id = CharField()
  863.  
  864. # Favorites List
  865. class UserFavorite(BaseModel):
  866. user_id = CharField()
  867. favorite_id = CharField()
  868. created = DateTimeField(default=datetime.datetime.now())
  869. identifier = IntegerField() # Identifier makes it easy for user to remove this favorite
  870.  
  871. # Muted management
  872. class MutedList(BaseModel):
  873. user_id = CharField()
  874. muted_id = CharField()
  875. muted_name = CharField()
  876. created = DateTimeField(default=datetime.datetime.now())
  877.  
  878. # Separate table for frozen so we can freeze even users not registered with bot
  879. class FrozenUser(BaseModel):
  880. user_id = IntegerField(unique=True)
  881. user_name = CharField()
  882. created = DateTimeField(default=datetime.datetime.now())
  883.  
  884.  
  885. def create_db():
  886. db.connect()
  887. db.create_tables([User, Transaction, Giveaway, Contestant, BannedUser, UserFavorite, MutedList, FrozenUser], safe=True)
  888. db.close()
  889.  
  890. create_db()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement