View difference between Paste ID: U6qQgijL and 968cwupe
SHOW: | | - or go back to the newest paste.
1
import curses
2
import curses.textpad
3
import requests
4
import json
5
import io
6
import os
7
import sys, getopt
8
from pathlib import Path
9
import re
10
import random
11
import time
12
import lupa
13
from parse import parse
14
import websocket
15
from requests.structures import CaseInsensitiveDict
16
17
18
19
server = 'just-dice.com'
20
21
username = "xxxx"
22
password = "xxxx"
23
24
_path = os.path.abspath(os.path.dirname(__file__))
25
account_file = Path(_path+'/account.jd')
26
27
class Config:
28
  def __init__(self):
29
    self.WS = None
30
    self.manualSession = False
31
    self.manualActive = False
32
    self.recovery = False
33
    self.exitOnMax = False
34
    self.noprofitensure = False
35
    self.stopbetting = False
36
    self.profitensure = False
37
    self.hitsFlag = False
38
    self.OnStopCmd = True
39
    self.alarmOn = True
40
    self.stopifwin = False
41
    self.balance = 0.0
42
    self.maxbalance = 0.0
43
    self.minbalance = 0.0
44
    self.bstart = -1.0
45
    self.before = 0
46
    self.SessionCookie = "c0ffee00000000000000000000c0ffee"
47
    self.sid = ""
48
    self.csrf = ""
49
    self.maxdiff = 0
50
    self.wagered = 0
51
    self.wincount = 0
52
    self.losecount = 0
53
    self.betcount = 0
54
    self.lastmax = 0
55
    self.lastmaxmax = 0
56
    self.currentstreak = 0
57
    self.currentprofit = 0
58
    self.minstreak = 0
59
    self.maxstreak = 0
60
    self.chance = 49.5
61
    self.chance2 = 57.0
62
    self.MaxPayIn = 0
63
    self.nextbet = 0.0000001
64
    self.basebet = self.nextbet
65
    self.goal = 0
66
    self.goalDelta = 0
67
    self.myRange = 0
68
    self.secret = 0
69
    self.win = None
70
    self.streakwin = [0 for i in range(204800)]
71
    self.streaklose = [0 for i in range(204800)]
72
    self.gain = 0
73
    self.keeplogfile = False
74
    self.kbd = 0
75
    self.infoval = ""
76
    self.testMode = False
77
    self.nobetdisplay = False
78
    self.bnowfile = _path+"/bnow.CLAM"
79
    self.exitReason = ""
80
    self.botname = ""
81
    self.begin = time.time()
82
    self.end = time.time()
83
    self.now = time.time()
84
    self.seconds = 0
85
    self.oldseconds = 0
86
    self.stopamount = 0.2
87
    self.percentualStop = 0
88
    self.turnlimit = 0
89
    self.profitensurance = 0
90
    self.lua = 0
91
    self.side = -1
92
_C = Config()
93
94
class Regions:
95
  def init(self, w):
96
    self.w = w
97
    (height, width) = w.getmaxyx ();
98
    self.height, self.width = (height, width) 
99
    self.header1 = curses.newwin (7, width//2-10, 0, 0)
100
    self.header2 = curses.newwin (7, width-self.header1.getmaxyx()[1], 0, self.header1.getmaxyx()[1]+1)
101
    self.stat = curses.newwin (2, width, 7, 0)
102
    heightavail=height-9
103
    self.betregion = curses.newwin (heightavail//2+4, width, 9+1, 0)
104
    self.manualline = curses.newwin (1, width, 9+self.betregion.getmaxyx()[0]+1, 0)
105
    self.msgregion = curses.newwin (heightavail//2-4, width, 9+self.betregion.getmaxyx()[0]+1+1, 0)
106
    self.betregion.scrollok(True)
107
    self.msgregion.scrollok(True)
108
    self.w.addstr(9, 0, "                  balance         chance        high             betsize           profit     lucky  ")
109
    w.refresh()
110
111
  def refresh (self, regions):
112
    for r in regions:
113
      getattr(self, r).refresh()
114
115
  def print_m_line(self, msg=""):
116
    if len(msg) == 0: # manual betting mode
117
      if not _C.manualActive: 
118
        self.clear_m_line()
119
        return
120
      if _C.balance > _C.before:
121
        s = "      +{:.8f}     D  {:.8f}".format(_C.balance-_C.before, _C.balance - _C.goal)
122
      else:
123
        s = "       {:.8f}     D  {:.8f}".format(_C.balance-_C.before, _C.balance - _C.goal)
124
      self.manualline.addstr(0, 0, "{:<14}{:>15.4f}% {:>15.4f}%{:>15.8f}{}".format("", _C.chance2, _C.chance, _C.nextbet, s))
125
      self.manualline.refresh()
126
    else: # msg mode
127
      self.clear_m_line()
128
      self.manualline.addstr(msg)
129
      self.manualline.refresh()
130
131
  def clear_m_line(self):
132
    self.manualline.move(0, 0)
133
    self.manualline.clrtoeol()
134
    self.manualline.refresh()
135
136
  # prints statistics in header1, header2 and stat regions
137
  def update_status(self):
138
    self.header1.attron(curses.color_pair(2))
139
    self.header1.addstr(0, 0, " minimum:{:15.8f}".format(_C.minbalance))
140
    self.header1.addstr(1, 0, " current:{:15.8f} ({:.8f})  ".format(_C.balance, _C.maxbalance-_C.stopamount))
141
    self.header1.addstr(2, 0, "    diff:{:15.8f} (max. {:.8f})  ".format(_C.maxbalance - _C.balance, _C.maxdiff))
142
    self.header1.addstr(3, 0, " maximum:{:15.8f}".format(_C.maxbalance))
143
    if _C.goal > 0 :
144
      self.header1.addstr(3, 25, "(goal: {:.8f})".format(_C.goal))
145
    self.header1.addstr(4, 0, "  profit:{:15.8f} ({:.3f}%)  ".format(_C.balance - _C.bstart, 
146
        0 if _C.bstart == 0 else float(_C.balance*100/_C.bstart-100)))
147
    self.header1.addstr(5, 0, "MaxPayIn:{:15.8f}".format(_C.MaxPayIn))
148
    self.header1.addstr(6, 0, " wagered:{:15.8f}".format(_C.wagered))
149
    self.header1.attroff(curses.color_pair(2))
150
151
    if _C.profitensure:
152
      self.header1.addstr(1,43, "{:.8f}".format(float((_C.bstart + _C.maxbalance)/200000000)), curses.color_pair(2))
153
154
    self.header1.refresh()
155
156
    _C.end = time.time()
157
    _C.seconds = int(_C.end - _C.begin)
158
    if _C.seconds > 0:
159
      betsPerSecond = float(_C.betcount/_C.seconds)
160
      profitPerSecond = (_C.balance-_C.bstart)/_C.seconds
161
    else:
162
      betsPerSecond = 0
163
      profitPerSecond = 0
164
    minutes = int(_C.seconds/60)
165
    hours = int(minutes/60)
166
    minutes = minutes%60
167
    _C.seconds = _C.seconds%60
168
169
    self.header2.addstr(1, 0, "won {} of {} bets ({:.4f}% {:.2f} bets/s )     ".format( 
170
      _C.wincount, _C.betcount, float(_C.wincount / _C.betcount * 100 if _C.betcount else 0), betsPerSecond))
171
    if _C.betcount - _C.lastmax > _C.lastmaxmax :
172
      _C.lastmaxmax = _C.betcount - _C.lastmax;
173
    self.header2.addstr(2, 0, "last max: {:>5} ({}) {:.2f}%     ".format( 
174
      _C.betcount - _C.lastmax, _C.lastmaxmax, float(_C.balance * 100 / _C.maxbalance if _C.maxbalance else 0)))
175
    self.header2.addstr(3, 0, "streak: {:>5} (min {} max {})    ".format(  
176
      _C.currentstreak, _C.minstreak, _C.maxstreak))
177
    if _C.seconds != _C.oldseconds:
178
      self.header2.addstr(4, 0, "{}:{:02}:{:02} {:0.2f}/min {:0.2f}/hour       ".format(
179
        hours,minutes,_C.seconds, profitPerSecond*60, profitPerSecond*3600))
180
      _C.oldseconds=_C.seconds
181
    self.header2.addstr(5, 0, f"info: {_C.infoval}")
182
    self.header2.refresh()
183
184
    for n in range(6,-1,-1):
185
      if -1*_C.minstreak - n > 0:
186
        self.stat.addstr(0, 1+n*6, "{:4}".format(-1*_C.minstreak - n), curses.color_pair(3))
187
        self.stat.addstr(1, 1+n*6, "{:4}".format(_C.streaklose[-1*_C.minstreak - n]))
188
    
189
    for n in range(6,-1,-1):
190
      if _C.maxstreak-n > 0:
191
        self.stat.addstr(0, self.width-16-n*6, "{:4}".format(_C.maxstreak-n), curses.color_pair(1))
192
        self.stat.addstr(1, self.width-16-n*6, "{:4}".format(_C.streakwin[_C.maxstreak-n]))        
193
    self.stat.refresh()
194
195
_R = Regions()
196
197
class HitsStat():
198
  min_hits = (250,125,100,65,55,40,33,27,24,20,15,13,10,9,8,7,7,6,5)
199
200
  def __init__(self):
201
    self.low = [{"count" : 0, "use" : False} for i in range(20)]
202
    self.high = [{"count" : 0, "use" : False} for i in range(20)]
203
    self.chances = []
204
    self.lowFlag = False
205
    self.highFlag = False
206
    self.chancesCurrent = 0
207
208
  def check(self, R):
209
    posLow = R // 500
210
    posHigh = 19 - posLow
211
    self.lowFlag = False
212
    self.highFlag = False
213
    for i in range(19):
214
      if posLow > i:
215
        self.low[i]["count"] += 1
216
        if self.low[i]["count"] >= self.min_hits[i]:
217
          self.low[i]["use"] = True
218
          self.lowFlag = True
219
      elif posLow <= i:
220
        self.low[i]["count"] = 0
221
        self.low[i]["use"] = False
222
223
      if posHigh > i:
224
        self.high[i]["count"] += 1
225
        if self.high[i]["count"] >= self.min_hits[i]:
226
          self.high[i]["use"] = True
227
          self.highFlag = True
228
      elif posHigh <= i:
229
        self.high[i]["count"] = 0
230
        self.high[i]["use"] = False
231
    return (self.lowFlag, self.highFlag)
232
233
  def once_in(self, count, chance):
234
    return 1/(1-chance/100)**count
235
236
  def print_msg(self):
237
    self.chances.clear()
238
    s = ""
239
    if self.lowFlag:
240
      s += "L: "
241
      for i in range(19):
242
        if self.low[i]["use"]:
243
          s += "c{} ({} once in {:.0f})| ".format((i+1)*5, self.low[i]["count"], self.once_in(self.low[i]["count"], (i+1)*5))
244
          self.chances.append((i+1)*5)
245
    if self.highFlag:
246
      s += "H: "
247
      for i in range(19):
248
        if self.high[i]["use"]:
249
          s += "c{} ({} once in {:.0f})| ".format((i+1)*5, self.high[i]["count"], self.once_in(self.high[i]["count"], (i+1)*5))
250
          self.chances.append((i+1)*5) 
251
    self.chances.append(57)
252
253
  def toggle_chances(self):
254
    if len(self.chances) > 0:
255
      if self.chancesCurrent >= len(self.chances):
256
        self.chancesCurrent = 0
257
      _C.chance2 = self.chances[self.chancesCurrent]
258
      self.chancesCurrent += 1
259
260
_H = HitsStat()
261
262
263
264
# converts float to string (to avoid scientific notation)
265
def float_to_str(f):
266
  float_string = repr(f)
267
  if 'e' in float_string:  # detect scientific notation
268
    digits, exp = float_string.split('e')
269
    digits = digits.replace('.', '').replace('-', '')
270
    exp = int(exp)
271
    zero_padding = '0' * (abs(int(exp)) - 1)
272
    sign = '-' if f < 0 else ''
273
    if exp > 0:
274
      float_string = '{}{}{}.0'.format(sign, digits, zero_padding)
275
    else:
276
      float_string = '{}0.{}{}'.format(sign, zero_padding, digits)
277
  return float_string
278
279
def login():
280
  con_cookies = {}
281
282
  headers = CaseInsensitiveDict()
283
  headers["Host"] = server
284
  headers["User-Agent"] = "'User-Agent': 'Firefox'"
285
  headers["Connection"] = "Keep-Alive"
286
287
  try:
288
    if account_file.is_file():
289
      with open(account_file) as data_file:
290
        con_cookies = json.load(data_file)
291
    else:
292
      headers["Cookie"] = "hash=b30adf82007d8544fa8ac14227ace6dfd1f7c1ee0b39c951ea101798cda5bbdb"
293
      response = requests.get(f"https://{server}/", headers=headers)
294
      if 'Set-Cookie' in response.headers.keys():
295
        con_cookies["sid"] = response.headers['Set-Cookie'].split(";")[0].split("=")[1]
296
297
      headers["Cookie"] = f"hash=b30adf82007d8544fa8ac14227ace6dfd1f7c1ee0b39c951ea101798cda5bbdb; connect.sid={con_cookies['sid']}"
298
      d = {'username' : username, 'password' : password, 'code' : ""}
299
      response = requests.post(f"https://{server}", data=d, headers=headers)
300
      if 'Set-Cookie' in response.headers.keys():
301
        con_cookies["hash"] = response.headers['Set-Cookie'].split(";")[0].split("=")[1]
302
303
304
      with io.open(account_file, 'w', encoding='utf8') as outfile:
305
        str_ = json.dumps(con_cookies,
306
                          indent=4, sort_keys=True,
307
                          separators=(',', ': '), ensure_ascii=False)
308
        outfile.write(str(str_))
309
310
311
312
    headers["Referer"] = f"https://{server}/"
313
    headers["Cookie"] = f"hash={con_cookies['hash']}; connect.sid={con_cookies['sid']}"
314
    response = requests.get(f"https://{server}/socket.io/?EIO=3&transport=polling&t={int(time.time()*1000)}-0", 
315
      headers=headers)
316
    if 'Set-Cookie' in response.headers.keys():
317
      con_cookies["io"] = response.headers['Set-Cookie'].split(";")[0].split("=")[1]
318
319
    headers["Cookie"] = f"io=3{con_cookies['io']}; hash={con_cookies['hash']}; connect.sid={con_cookies['sid']}"
320
    response = requests.get(
321
      f"https://{server}/socket.io/?EIO=3&transport=polling&t={int(time.time()*1000)}-1&sid={con_cookies['io']}", 
322
      headers=headers)
323
324
    rest_txt = response.text.split("ÿ42")[1]
325
    rest_txt = rest_txt[:rest_txt.rfind("]")+1]
326
327
    stats = json.loads(rest_txt)[1]
328
    del stats["chat"]
329
    _C.csrf = stats["csrf"] 
330
    _C.sid = con_cookies['io']
331
    _C.SessionCookie = headers["Cookie"]
332
    _C.balance = float(stats["balance"])
333
    _C.uid = stats['uid']
334
    return True
335
336
  except Exception as err:
337
    _C.exitReason = f"login error ({err})"
338
    return False
339
340
341
342
########################################################
343
def do_bet(bet):
344
  try:
345
    _C.WS.send(bet)
346
    result = _C.WS.recv()
347
    waiting = True
348
    count = 0
349
    while waiting:
350
      count += 1
351
      if "result" in result:
352
        r = json.loads(result[2:])[1]
353
        if r['uid'] == _C.uid:
354
          return result
355
      if "jderror" in result or count > 20:
356
        msg(f"Count: {count}")
357
        msg(result)
358
        waiting = False
359
        break
360
      result = _C.WS.recv()
361
    _C.exitReason = f'Bet error ({result})'  
362
    return None
363
364
365
  except Exception as err:
366
    _C.exitReason = f'Bet request -  error occurred: {err}'
367
    return None
368
369
370
def text_input(old_value, h, w, y, x):
371
  window = curses.newwin(h, w, y, x)
372
  window.clear()
373
  curses.curs_set(1)
374
  window.bkgd(' ', curses.color_pair(2) | curses.A_BOLD | curses.A_REVERSE)
375
  window.addstr(0, 0, float_to_str(old_value))
376
  window.refresh()
377
  textbox = curses.textpad.Textbox(window)
378
379
  class EscapeInterrupt(Exception):
380
    "Signal that the ESC key has been pressed"
381
  def validate(ch):
382
    if ch == 27:
383
      raise EscapeInterrupt()
384
    # Fix backspace for iterm
385
    if ch not in (10, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 262, 260, 330, 360, 261, 127):
386
      return 12
387
    if ch == curses.KEY_HOME: #
388
      ch = 1
389
    if ch == curses.KEY_LEFT:
390
      ch = 2
391
    if ch == 330: # DEL
392
      ch = 4
393
    if ch == curses.KEY_END:
394
      ch = 5
395
    if ch == curses.KEY_RIGHT:
396
      ch = 6
397
    if ch == 127: # BACKSPACE
398
      ch = 263
399
    return ch
400
  try:
401
    out = textbox.edit(validate=validate)
402
  except EscapeInterrupt:
403
    out = str(old_value)
404
  try:
405
    float(out)
406
  except ValueError:
407
    out = str(old_value)
408
  curses.curs_set(0)
409
  window.erase()
410
  del window
411
  return out
412
413
414
def get_random_int(a,b):
415
  return random.SystemRandom().randint(a, b)
416
417
418
def init_lua():
419
  source = open(_C.botname).read()
420
  _C.lua.globals()["balance"] = _C.balance
421
  _C.lua.globals()["print"] = msg
422
  _C.lua.globals()["stop"] = stoplua
423
  _C.lua.globals()["infoval"] = ""
424
  _C.lua.globals()["side"] = _C.side
425
  _C.lua.execute(source)
426
  _C.chance = float(int(_C.lua.globals()["chance"]*10000)/10000)
427
  _C.nextbet = _C.lua.globals()["nextbet"]
428
  _C.basebet = _C.nextbet;
429
  _C.side = _C.lua.globals()["side"]
430
431
432
class BetInfo:
433
  def __init__(self, betsize, chance, side=0):
434
    if side == 0:
435
      self.Which = "lo" if get_random_int(0, 999999) < 500000 else "hi"
436
    elif side == -1:
437
      self.Which = "lo"
438
    else:
439
      self.Which = "hi"
440
    self.BetSize = betsize
441
    self.Chance = chance
442
443
  def set_result(self, res):
444
    res = json.loads(res[2:])[1]
445
    self.bet = res['bet']
446
    self.betid = res['betid']
447
    self.chance = float(res['chance'])
448
    self.high = res['high']
449
    self.lucky = int(res['lucky'])
450
    self.payout = float(res['payout'])
451
    self.profit = float(res['this_profit'])
452
    self.win = res['win']
453
    self.balance = float(res['balance'])
454
455
456
457
  def request(self, log=False) :
458
    bet = {"chance" : self.Chance, "bet" : self.BetSize, "which" : self.Which}
459
    return f'42["bet","{_C.csrf}",{{"chance":"{bet["chance"]}","bet":"{bet["bet"]:.8f}","which":"{bet["which"]}"}}]' if not log else bet
460
461
462
463
def betlog(line):
464
  logfile = open(_path+"/betlog", "a")
465
  logfile.write(f"{line}\n")
466
  logfile.close()
467
  if os.stat(_path+"/betlog").st_size > 10485760 and not _C.keeplogfile:
468
    os.rename(_path+"/betlog",_path+"/betlog.old")
469
470
471
def interactive_mode():
472
  _C.nobetdisplay = False
473
  if _C.OnStopCmd and _C.alarmOn:
474
    print("\a")
475
    _C.alarmOn = False
476
  if not _C.hitsFlag:
477
    _C.goal = _C.maxbalance
478
  ekey = 1
479
  ekey = _R.w.getch()
480
  while ekey not in (ord("q"), ord("c"), ord("m"), ord('+'), ord('w')):
481
    _R.w.timeout(5)
482
    ekey = _R.w.getch()
483
    if _C.balance > _C.maxbalance:
484
      ekey = ord("q")
485
    if ekey == ord("q"):
486
      _C.kbd = ord("Q")
487
      return 0
488
    if ekey == ord("m"):
489
      _C.hitsFlag = False
490
      manual_mode()
491
      return 0
492
    if ekey == ord("w") and not _C.hitsFlag:
493
      _C.stopifwin = True
494
    if ekey == ord("c"):
495
      _C.stopifwin = False
496
    if ekey == ord("+"):
497
      _C.stopamount *= 110/100
498
  return 0    
499
500
501
502
def bet(betsize, side=0, chance=None):
503
  if chance is None:
504
      chance = _C.chance
505
  b = BetInfo(betsize, chance, side)
506
507
  if b.BetSize > _C.MaxPayIn:
508
    _C.MaxPayIn = b.BetSize
509
  _C.wagered += b.BetSize;
510
511
512
  if not _C.noprofitensure:
513
    if _C.balance > _C.bstart * 2 and _C.bstart > 0:
514
      _C.profitensure = True
515
      _R.header1.addstr(1, 29, "STOP2 @", curses.color_pair(3) | curses.A_BOLD)
516
    if _C.maxdiff > 2000*_C.basebet and _C.balance > _C.bstart + 2*_C.maxdiff and _C.bstart > 0:
517
      _C.profitensure = True
518
      _R.header1.addstr(1, 29, "STOP3 @", curses.color_pair(3) | curses.A_BOLD)
519
    if _C.maxbalance - 2000*_C.basebet > _C.bstart and _C.bstart > 0:
520
      _C.profitensure = True
521
      _R.header1.addstr(1, 29, "STOP4 @", curses.color_pair(3) | curses.A_BOLD)
522
    if _C.profitensurance > 0 and _C.maxbalance - _C.profitensurance > _C.bstart and _C.bstart > 0:
523
      _C.profitensure = True
524
      _R.header1.addstr(1, 29, "STOP5 @", curses.color_pair(3) | curses.A_BOLD)
525
  
526
  if _C.hitsFlag:
527
    _R.betregion.addstr("\nHits STOP. ", curses.color_pair(2) | curses.A_BOLD)
528
    _R.betregion.addstr("Press ")
529
    _R.betregion.addstr("c", curses.color_pair(2) | curses.A_BOLD)
530
    _R.betregion.addstr("ontinue / ")
531
    _R.betregion.addstr("q", curses.color_pair(2) | curses.A_BOLD)
532
    _R.betregion.addstr("uit / ")
533
    _R.betregion.addstr("m", curses.color_pair(2) | curses.A_BOLD)
534
    _R.betregion.addstr("anual (")
535
    _R.betregion.addstr("w", curses.color_pair(2) | curses.A_BOLD)
536
    _R.betregion.addstr(" - single bet, ")
537
    _R.betregion.addstr("+", curses.color_pair(2) | curses.A_BOLD)
538
    _R.betregion.addstr(" - stopamount*1.1)\n")
539
    _R.betregion.refresh()
540
541
    if not _C.manualActive:
542
      interactive_mode()
543
    if _C.kbd == ord("Q"):
544
      return 0
545
546
  else:
547
    if not _C.manualActive:
548
      if _C.balance >= _C.goal and _C.goal > 0:
549
        _C.exitReason = "GOAL REACHED {:.8f} >= {:.8f}".format(_C.balance, _C.goal)
550
        _C.kbd = ord("Q")
551
        return 0
552
553
  betlog(b.request(log=True))
554
555
  
556
  res = do_bet(b.request())
557
558
  if res is None:
559
    _C.stopbetting = True
560
    msg(f'chance: {b.Chance} amount : {b.BetSize:.8f}')
561
    msg(b.request())
562
    msg(_C.exitReason)
563
    return 0
564
  else:
565
    b.set_result(res)
566
    betlog(f'{res}'.replace("'",'"').replace(" ", ""))
567
    _C.secret = b.lucky/10000
568
569
    if _C.bstart == -1:
570
      _C.bstart = b.balance - b.bet
571
572
    h_l = " "
573
    if _C.secret < 49.5:
574
      h_l = "L"
575
    elif _C.secret >= 50.5:
576
      h_l = "H"
577
    l_30 = " ";
578
    h_30 = " ";
579
    if _C.secret < 30.0000001: l_30 = "|"
580
    if _C.secret > 70.0000: h_30 = "|"
581
582
583
    _C.hitsFlag = any(_H.check(_C.secret*100))
584
    if _C.hitsFlag:
585
      _H.print_msg()
586
587
    _C.balance = b.balance
588
    bprofit = b.profit
589
    _C.currentprofit = b.profit
590
    oncein = 1
591
    if b.win : #win
592
      color = 1
593
      color2 = 1
594
      _C.win = True
595
      if _C.currentstreak < 0:
596
        _C.streaklose[-1*_C.currentstreak] +=1
597
        _C.currentstreak = 1
598
        oncein = 100/_C.chance
599
      else:
600
        _C.currentstreak += 1
601
        oncein *= 100/chance
602
        if oncein + 0.9 >= 8000:
603
          _R.msgregion.addstr("{:12}: {:0.8f} {:0.8f} streak {:3} (once in {})\n".format(
604
            _C.betcount, _C.balance, _C.gain, _C.currentstreak, int(oncein+0.9)))
605
          _R.msgregion.refresh()
606
      _C.wincount += 1
607
    else:
608
      color2 = 3
609
      _C.win = False
610
      if _C.currentstreak > 0:
611
        _C.streakwin[_C.currentstreak] +=1
612
        _C.currentstreak = -1
613
        oncein = 100/(100-_C.chance)
614
      else:
615
        _C.currentstreak -= 1
616
        oncein *= 100/(100-_C.chance)
617
        if oncein + 0.9 >= 8000:
618
          _R.msgregion.addstr("{:12}: {:0.8f} {:0.8f} streak {:3} (once in {})\n".format(
619
            _C.betcount, _C.balance, _C.gain, _C.currentstreak, int(oncein+0.9)))
620
          _R.msgregion.refresh()
621
      _C.losecount += 1
622
623
    if _C.currentstreak < _C.minstreak:
624
      _C.minstreak = _C.currentstreak;
625
    if _C.currentstreak > _C.maxstreak:
626
      _C.maxstreak = _C.currentstreak;
627
    _C.betcount += 1
628
629
    if (_C.balance >= _C.maxbalance):
630
      _C.gain = _C.balance - _C.maxbalance
631
      _C.maxbalance = _C.balance
632
      _C.maxbets = _C.betcount - _C.lastmax
633
      _C.lastmax = _C.betcount
634
      _R.betregion.attron(curses.A_BOLD)
635
636
      if _C.exitOnMax or _C.turnlimit > 0 and _C.betcount > _C.turnlimit:
637
        _C.exitReason = f'EXIT on MAX requested'
638
        _C.kbd = ord('Q')
639
640
641
    if _C.balance < _C.minbalance:
642
      _C.minbalance = _C.balance
643
    if (_C.maxbalance - _C.balance) > _C.maxdiff:
644
      _C.maxdiff = _C.maxbalance - _C.balance
645
646
    if not _C.testMode:
647
      if not _C.nobetdisplay or _C.manualActive:
648
        color = int(_C.balance*100/_C.maxbalance) if _C.maxbalance > 0 else 0
649
        if color < 86: 
650
          color = 86
651
        _R.betregion.attron(curses.color_pair(color2))
652
653
        if _C.balance < _C.maxbalance:
654
          _R.betregion.addstr("{} ".format(h_l))
655
          _R.betregion.addstr("{:4} {:4} ".format(abs(_C.currentstreak), _C.betcount-_C.lastmax))
656
          _R.betregion.addstr("{:18.8f}  ".format(_C.balance), curses.color_pair(color))
657
          _R.betregion.addstr("{}{:5.4f}%{}  {:^13} {:16.8f}  {:16.8f}  {:<9} \n".format(
658
            l_30, chance, h_30, str(b.high), betsize, bprofit, _C.secret))
659
        else:
660
          _R.betregion.addstr("{} {:4} {:4} {:18.8f}  {}{:5.4f}%{}  {:^13} {:16.8f}  {:16.8f}  {:<9} +{:.8f}\n".format(
661
            h_l, 
662
            abs(_C.currentstreak), 
663
            _C.betcount-_C.lastmax, 
664
            _C.balance,
665
            l_30,
666
            chance, 
667
            h_30, str(b.high), 
668
            betsize, 
669
            bprofit, 
670
            _C.secret, 
671
            _C.gain))
672
673
        _R.betregion.attroff(curses.color_pair(color))
674
        _R.betregion.attroff(curses.A_BOLD)
675
        _R.betregion.refresh()
676
677
    _R.update_status()
678
679
    logfile = open(_C.bnowfile, "a")
680
    logfile.write("{}:{:.8f}\n".format(0, _C.balance))
681
    logfile.close()
682
683
684
685
def manual_mode():
686
  cred = 0
687
  localcount = 0 
688
  _C.manualActive= True
689
  _C.before= _C.balance
690
  if _C.manualSession:
691
    _C.nextbet = 0.00000001
692
    _C.basebet = _C.nextbet
693
  else:
694
    _C.recovery = True
695
  
696
  _R.update_status()
697
  _C.kbd = _R.w.getch()
698
  _C.now = time.time()
699
  while _C.kbd not in (ord("Q"), ord("D"), ord("X")):
700
    if _C.exitOnMax and _C.balance>=_C.maxbalance:
701
      msg(f"{_C.goal} - {_C.balance - _C.goal}")
702
      _C.kbd = ord("Q")
703
      continue
704
    if _C.balance - _C.goal > 0 and _C.goal > 0:
705
      msg(f"{_C.goal} - {_C.balance - _C.goal}")
706
      _C.kbd = ord("Q")
707
      continue
708
709
710
    _R.print_m_line()
711
    _R.w.timeout(5)
712
    _C.kbd = _R.w.getch()
713
714
    if   _C.kbd == ord('z'):
715
      _C.nextbet *= 2 
716
      if _C.nextbet > _C.balance:
717
        _C.nextbet = _C.balance-0.00000001
718
719
    elif _C.kbd == ord('x'):
720
      _C.nextbet /= 2 
721
      if _C.nextbet < 0.00000001:
722
        _C.nextbet = 0.00000001
723
724
    elif   _C.kbd == ord('a'):
725
      _C.nextbet *= 1.5 
726
      if _C.nextbet > _C.balance:
727
        _C.nextbet = _C.balance-0.00000001
728
729
    elif _C.kbd == ord('s'):
730
      _C.nextbet /= 1.5 
731
      if _C.nextbet < 0.00000001:
732
        _C.nextbet = 0.00000001
733
734
    elif _C.kbd == ord('u'):
735
      _H.toggle_chances()
736
737
    elif _C.kbd == ord('R'):
738
      if len(_C.botname):
739
        msg("Restart lua")
740
        init_lua()
741
        _C.stopbetting = False
742
        _C.kbd = ord('X')
743
        if _C.goalDelta > 0:
744
          _C.goal = _C.balance + _C.goalDelta
745
      else:
746
        msg("Run with botname argument")
747
748
    elif   _C.kbd == ord('m'):
749
      if _C.chance > 5 and _C.chance < 95:      
750
        _C.chance -= 5
751
      else:
752
        _C.chance -=1
753
      if _C.chance < 0.0001: _C.chance = 0.0001
754
755
    elif   _C.kbd == ord('n'):
756
      if _C.chance >= 95 or _C.chance < 5: 
757
        _C.chance += 1
758
      else:
759
        _C.chance += 5
760
      if _C.chance > 98.99: _C.chance = 98.99
761
762
    elif   _C.kbd == ord('1'):
763
      _C.chance = 5
764
765
    elif   _C.kbd == ord('5'):
766
      _C.chance = 50 if _C.chance == 49.5 else 49.5
767
768
    elif _C.kbd == ord('`'):
769
      _C.nextbet = 0.00000001
770
771
    elif _C.kbd == ord('7'):
772
      _C.chance = 70
773
774
    elif _C.kbd == ord('E'):
775
      nextbet = float("{:0.8f}".format(_C.nextbet))
776
      _C.nextbet = float(text_input(nextbet, *(1, 18, _R.manualline.getbegyx()[0], 49)))
777
778
    elif _C.kbd == curses.ascii.ENQ:
779
      _C.chance = float(text_input(_C.chance, *(1, 15, _R.manualline.getbegyx()[0], 34)))
780
    
781
    elif _C.kbd == ord('l'):
782
      bet(_C.nextbet)
783
784
    elif _C.kbd == ord('o'):
785
      bet(_C.nextbet, chance=_C.chance2)
786
787
    elif _C.kbd == ord('['):
788
      bet(_C.nextbet, -1, chance=_C.chance2)
789
790
    elif _C.kbd == ord(']'):
791
      bet(_C.nextbet, 1, chance=_C.chance2)
792
793
    elif _C.kbd == ord(','):
794
      bet(_C.nextbet, -1)
795
796
    elif _C.kbd == ord('.'):
797
      bet(_C.nextbet, 1)
798
799
    elif _C.kbd == ord('e'):
800
      _C.goal += 0.25
801
      _C.maxbalance += 0.25
802
      _R.update_status()
803
    elif _C.kbd == ord('r'):
804
      _C.goal -= 0.25
805
      _C.maxbalance -= 0.25
806
      _R.update_status()
807
      
808
809
    elif _C.kbd == ord('0'):
810
      _R.print_m_line("testMode is On. Press 'X' to stop")
811
      _C.nextbet = 0.00000004
812
      cred = 100000
813
      start = _C.betcount
814
      while cred > 0 and _C.currentstreak > -7:
815
        bet(_C.nextbet, -1)
816
        cred -= 1
817
        if _C.hitsFlag:
818
          cred = 0;
819
        if _R.w.getch() == ord("X"):
820
          _R.msgregion.addstr("testMode is off\n")
821
          _R.msgregion.refresh()
822
          cred = 0
823
      _R.msgregion.addstr("{:12} ({}) ".format(_C.betcount, _C.betcount-start))
824
      _R.msgregion.addstr("hunt streak {:3} (low)\n".format(_C.currentstreak), curses.color_pair(2))
825
      _R.msgregion.refresh()
826
827
828
    else:
829
      if _C.kbd>0: 
830
        _R.msgregion.addstr("you pressed {} - Edit your code to make it do something useful\n".format(curses.unctrl(_C.kbd)))
831
        _R.msgregion.refresh()
832
  _C.manualActive = False
833
  _R.clear_m_line()
834
def msg(s):
835
  _R.msgregion.addstr("{:12}: ".format(_C.betcount))
836
  _R.msgregion.addstr("{}\n".format(s), curses.color_pair(2))
837
  _R.msgregion.refresh()
838
839
def stoplua():
840
  bailout("\nStop() called\n"+
841
  "\nBalance: {:13.8f} {}\n\033[0m".format(_C.balance, "CLAM")+
842
  "Profit: {:13.8f} {} ({:2f}%)\n\033[0m".format(_C.balance - _C.bstart, "CLAM", float((_C.balance-_C.bstart)*100/_C.bstart) if _C.bstart > 0 else 0)+
843
  "\n {} bets done in {} seconds ({:2f} bets/sec) ".format(_C.betcount, _C.seconds,float(_C.betcount/_C.seconds) if _C.seconds else _C.betcount))
844
  return 1
845
846
def bailout(msg):
847
  curses.endwin()
848
  print("\nFATAL ERROR:\n  {}\n\n".format(msg))
849
  # quit()
850
  sys.exit(9)
851
852
853
def curses_main(w):
854
  curses.curs_set(0);
855
  curses.cbreak();
856
  curses.noecho();
857
  w.nodelay (True);
858
  curses.mousemask(curses.BUTTON3_CLICKED)
859
  w.refresh()
860
  curses.start_color()
861
  curses.use_default_colors();
862
  curses.init_pair (1, curses.COLOR_GREEN, -1);
863
  curses.init_pair (2, curses.COLOR_YELLOW, -1);
864
  curses.init_pair (3, curses.COLOR_RED, -1);
865
  curses.init_pair (4, curses.COLOR_CYAN, -1);
866
  curses.init_pair (5, curses.COLOR_WHITE, -1);
867
  curses.init_pair (100, curses.COLOR_GREEN, -1); 
868
  curses.init_pair (99, 48, -1);
869
  curses.init_pair (98, 82, -1);
870
  curses.init_pair (97,118, -1);
871
  curses.init_pair (96,154, -1);
872
  curses.init_pair (95,190, -1);
873
  curses.init_pair (94,226, -1);
874
  curses.init_pair (93,220, -1);
875
  curses.init_pair (92,214, -1);
876
  curses.init_pair (91,208, -1);
877
  curses.init_pair (90,202, -1);
878
  curses.init_pair (89,196, -1);
879
  curses.init_pair (88,160, -1);
880
  curses.init_pair (87,124, -1);
881
  curses.init_pair (86, 88, -1);
882
883
  _R.init(w)
884
  _R.header2.addstr("{}: {}".format(_path, _C.botname))
885
  
886
  _R.w.refresh()
887
  _R.refresh(["header1", "header2", "stat", "betregion", "msgregion"])
888
  _R.print_m_line()
889
890
  
891
  if not login():
892
    return 0
893
  
894
  _C.WS = websocket.create_connection(f"wss://{server}/socket.io/?EIO=3&transport=websocket&sid={_C.sid}",
895
    cookie = _C.SessionCookie)
896
  _C.WS.send('2probe')
897
  _C.WS.recv()
898
  _C.WS.send('5')
899
  _C.WS.recv()
900
901
  _C.maxbalance=_C.balance;
902
  _C.minbalance=_C.balance;
903
  _C.bstart=_C.balance;
904
905
  _R.update_status()
906
907
  if _C.goalDelta > 0:
908
    _C.goal = _C.balance + _C.goalDelta
909
  if _C.percentualStop > 100:
910
    _C.percentualStop = 100
911
  if _C.percentualStop > 0:
912
    _C.stopamount = _C.balance*_C.percentualStop/100
913
914
  _C.kbd = -1
915
  if _C.manualSession:
916
    manual_mode();
917
  else:
918
    _C.lua  = lupa.LuaRuntime()
919
    try:
920
      init_lua()
921
922
    except Exception as err:
923
      bailout(err)
924
925
    while _C.kbd not in (ord("Q"), ord("D")):
926
      w.timeout (0)
927
      _C.kbd = w.getch()
928
      if _C.kbd > 0 :
929
        if _C.kbd == ord('h'):
930
          _C.stopamount *= 110/100
931
          _C.stopbetting = False
932
933
        elif _C.kbd == ord('c'):
934
          msg("Continue pressed...")
935
          _C.stopbetting = False
936
937
        elif _C.kbd == ord('p'):
938
          _C.stopbetting = True
939
          msg("Pause pressed...")
940
941
        elif _C.kbd == ord('M'):
942
          msg("manualMode pressed...")
943
          manual_mode()
944
945
        elif _C.kbd == ord('N'):
946
          _C.nobetdisplay = not _C.nobetdisplay
947
          msg(f"nobetdisplay is {'ON' if _C.nobetdisplay else 'OFF'}")
948
949
        elif _C.kbd == ord('s'):
950
          _R.header1.addstr(1, 30, "STOP5 @", curses.color_pair(3) | curses.A_BOLD)
951
          _C.profitensure = True
952
953
        elif _C.kbd == ord('x'):
954
          _R.header1.addstr(0, 32, "EXIT on MAX balance", curses.color_pair(4) | curses.A_BOLD) 
955
          _C.exitOnMax = True
956
957
        if _C.goal > 0 and _C.balance > _C.goal:
958
          _C.exitOnMax = True
959
960
      if not _C.stopbetting:
961
        bet(_C.nextbet, _C.side)
962
        _C.sessionprofit = _C.balance - _C.bstart;
963
        _C.lua.globals()["balance"] = _C.balance
964
        _C.lua.globals()["secret"] = _C.secret
965
        _C.lua.globals()["win"] = _C.win
966
        _C.lua.globals()["profit"] = _C.sessionprofit
967
        _C.lua.globals()["currentprofit"] = _C.currentprofit
968
        _C.lua.globals()["currentstreak"] = _C.currentstreak
969
        _C.lua.globals()["previousbet"] = _C.nextbet
970
        _C.lua.globals()["bets"] = _C.betcount
971
        _C.lua.globals()["wins"] = _C.wincount
972
        _C.lua.globals()["losses"] = _C.losecount
973
        _C.lua.globals()["info"] = ""
974
        _C.lua.globals()["side"] = _C.side
975
976
        _C.lua.globals().dobet()
977
978
        _C.chance = float(int(_C.lua.globals()["chance"]*100)/100)
979
        _C.nextbet = _C.lua.globals()["nextbet"]
980
        _C.basebet = _C.nextbet;
981
        _C.infoval = _C.lua.globals()["info"]
982
        _C.side = _C.lua.globals()["side"]
983
984
985
986
987
def print_usage_info() :
988
  print("call it as: python main.py [options] <name_of_your_lua_file>");
989
  print("\noptions:");
990
  print(" -m             # start a manual session\n");
991
992
993
994
def main(argv):
995
  """
996
  The curses.wrapper function is an optional function that
997
  encapsulates a number of lower-level setup and teardown
998
  functions, and takes a single function to run when
999
  the initializations have taken place.
1000
  """
1001
1002
  if len(argv) == 0 :
1003
    print_usage_info()
1004
    #login()
1005
  else :
1006
    try:
1007
      opts, args = getopt.getopt(argv, "mH:h:knNXt:g:G:P:")
1008
    except getopt.GetoptError:
1009
      print_usage_info()
1010
      quit()
1011
    for opt, arg in opts :
1012
      if opt == "-m":
1013
        _C.manualSession = True
1014
        continue
1015
      elif opt == "-H":
1016
        _C.stopamount = float(arg)
1017
        continue
1018
      elif opt == "-h":
1019
        _C.percentualStop = float(arg)
1020
        continue
1021
      elif opt == "-k":
1022
        _C.keeplogfile = True
1023
        continue
1024
      elif opt == "-n":
1025
        _C.noprofitensure = True
1026
        continue
1027
      elif opt == "-N":
1028
        _C.nobetdisplay = True
1029
        continue
1030
      elif opt == "-t":
1031
        _C.turnlimit = int(arg)
1032
        continue
1033
      elif opt == "-g":
1034
        _C.goal = float(arg)
1035
        continue
1036
      elif opt == "-G":
1037
        _C.goalDelta = float(arg)
1038
        continue
1039
      elif opt == "-P":
1040
        _C.profitensurance = float(arg)
1041
        continue
1042
      else:
1043
        print ("Unknown option {} ({})".format(opt, arg))
1044
        quit()
1045
1046
1047
    if not _C.manualSession: 
1048
      if args:
1049
        _C.botname = args[-1]
1050
      else:
1051
        print ("you forgot botname\n")  
1052
        print_usage_info()
1053
        quit()
1054
    curses.wrapper(curses_main)
1055
    curses.endwin()
1056
1057
    _C.WS.close()
1058
1059
    if _C.betcount:
1060
      logfile = open(_path+"/pybot.log", "a")
1061
      line = "{} ".format(int(time.time())) 
1062
      line += "won {} of {} bets ({:.2f}%) at {:.2f}% chance, ".format(_C.wincount, _C.betcount,
1063
        float(_C.wincount/_C.betcount*100), _C.chance)
1064
      line += "Balance: {:.8f} {}, ".format(_C.balance, "CLAM")
1065
      line += " bmax: {:.8f} ".format(_C.maxbalance)
1066
      line += " lastmaxmax: {} ".format(_C.lastmaxmax)
1067
      line += " MaxPayIn: {:.8f}  ".format(_C.MaxPayIn)
1068
      line += " minstreak: {}, maxstreak: {}, maxdiff: {:.8f}".format(_C.minstreak, _C.maxstreak, _C.maxdiff)
1069
      line += ", {}, ".format(_C.botname)
1070
      line += "{} \n".format(_C.exitReason)
1071
      logfile.write(line)
1072
      logfile.close()
1073
1074
1075
      _C.seconds = int (_C.end - _C.begin)
1076
      print("\n"*(_R.height-30))
1077
      print("\033[1m\n\npybot exit: {}\n".format(_C.exitReason))
1078
      print(" Balance: {:13.8f} {}\n\033[0m".format(_C.balance, "CLAM"))
1079
      print(" Profit: {:13.8f} {} ({:2f}%)\n\033[0m".format(
1080
        _C.balance - _C.bstart, 
1081
        "CLAM", float((_C.balance-_C.bstart)*100/_C.bstart) if _C.bstart > 0 else 0))
1082
      print("\n {} bets done in {} seconds ({:2f} bets/sec) ".format(
1083
        _C.betcount, _C.seconds,float(_C.betcount/_C.seconds) if _C.seconds else _C.betcount))
1084
      print(" bmax: {:.8f} ".format(_C.maxbalance))
1085
      print(" MaxPayIn: {:.8f}\n".format(_C.MaxPayIn))
1086
      print(" minstreak: {}, maxstreak: {}, ".format(_C.minstreak, _C.maxstreak))
1087
      print(" maxdiff: {:.8f} \n".format(_C.maxdiff))
1088
    else:
1089
      print("\033[1m\n\npybot exit: {}\n".format(_C.exitReason))
1090
      print("\033[1m\n\npybot exit: no betting :P\n\033[0m")
1091
1092
    if (_C.kbd == ord('D')):
1093
      sys.exit(9)
1094
main(sys.argv[1:])
1095