예제 #1
0
파일: reddit.py 프로젝트: clintar/tippero
  def connect(self):
    if self.thread:
      return False
    try:
      cfg=config.network_config[self.name]
      self.login=cfg['login']
      password=GetPassword(self.name)
      self.subreddits=cfg['subreddits']
      user_agent=cfg['user_agent']
      self.update_period=cfg['update_period']
      self.load_limit=cfg['load_limit']
      self.keyword=cfg['keyword']
      self.use_unread_api=cfg['use_unread_api']
      self.cache_timeout=cfg['cache_timeout']

      self.reddit=praw.Reddit(user_agent=user_agent,cache_timeout=self.cache_timeout)
      self.reddit.login(self.login,password)
      self.items_cache=dict()

      self.stop = False
      self.thread = threading.Thread(target=self.run)
      self.thread.start()
      self.logged_in=True

    except Exception,e:
      log_error('Failed to login to reddit: %s' % str(e))
      return False
예제 #2
0
파일: irc.py 프로젝트: clintar/tippero
  def _connect(self,host,port,login,password,delay):
    self.host=host
    self.port=port
    self.login=login
    self.password=password
    self.line_delay=delay

    log_info('Connecting to IRC at %s:%u' % (host, port))
    self.last_send_time=0
    self.last_ping_time = time.time()
    self.quitting = False
    self.buffered_data = ""
    self.userstable=dict()
    self.registered_users=set()
    try:
      self.irc = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
      if self.use_ssl:
        try:
          raise RuntimeError('')
          self.irc_ssl_context = ssl.create_default_context()
          self.sslirc = self.irc_ssl_context.wrap_socket(self.irc, host)
          self.sslirc.connect ( ( host, port ) )
        except Exception,e:
          log_warn('Failed to create SSL context, using fallback code: %s' % str(e))
          self.irc.connect ( ( host, port ) )
          self.sslirc = socket.ssl(self.irc)
    except Exception, e:
      log_error( 'Error initializing IRC: %s' % str(e))
      return False
예제 #3
0
파일: bookie.py 프로젝트: clintar/tippero
def Bookie(link,cmd):
  identity=link.identity()

  name = GetParam(cmd,1)
  if not name:
    link.send('usage: !bookie <name> <outcome1> <outcome2> [<outcome3>...]')
    return
  outcomes = cmd[2:]
  if len(outcomes) < 2:
    link.send('usage: !bookie <name> <outcome1> <outcome2> [<outcome3>...]')
    return

  book_index=long(redis_get('bookie:last_book') or 0)
  book_index += 1
  tname = "bookie:%d" % book_index

  log_info('%s opens book #%d for %s, with outcomes %s' % (identity, book_index, name, str(outcomes)))
  try:
    p = redis_pipeline()
    p.hset(tname,'name',name)
    for o in outcomes:
      p.sadd(tname+':outcomes',o)
    p.hset('bookie:active',book_index,name)
    redis_set('bookie:last_book',book_index)
    p.execute()
  except Exception,e:
    log_error('Bookie: Failed to register book for %s with outcomes %s: %s' % (name, str(outcomes), str(e)))
    link.send('Failed to create book')
    return
예제 #4
0
파일: twitter.py 프로젝트: clintar/tippero
  def _parse_tweet(self,msg):
    if msg.user.screen_name.lower() == self.login.lower() and not force_parse_self:
      log_log('Ignoring tweet from self')
      return

    log_info('Twitter: parsing tweet from %s: %s' % (msg.user.screen_name,msg.text))

    # twitter special: +x means tip the user mentioned with a @
    for line in msg.text.split('\n'):
      line=line.lower()
      line=line.replace(self.keyword,'',1).strip()
      log_log('After removal: %s' % line)
      if re.match(username_regexp+"[ \t]*"+amount_regexp,line) or re.match(amount_regexp+"[ \t]*"+username_regexp,line):
        link=Link(self,User(self,msg.user.screen_name),None,msg)
        match=re.search(username_regexp,line)
        if not match:
          continue
        target=match.group(0)
        match=re.search(amount_regexp,line.replace(target,'').strip())
        if not match:
          continue
        amount=match.group(0)
        if self.on_command:
          try:
            synthetic_cmd=['tip',target.replace('@','').strip(),amount.replace('+','').strip()]
            log_log('Running synthetic command: %s' % (str(synthetic_cmd)))
            self.on_command(link,synthetic_cmd)
          except Exception,e:
            log_error('Failed to tip %s: %s' % (target,str(e)))
예제 #5
0
파일: withdraw.py 프로젝트: clintar/tippero
def ValidateDNSSEC(address):
  log_info('Validating DNSSEC for %s' % address)
  try:
    resolver = dns.resolver.get_default_resolver()
    ns = resolver.nameservers[0]
    parts = address.split('.')
    for i in xrange(len(parts),0,-1):
      subpart = '.'.join(parts[i-1:])
      query = dns.message.make_query(subpart,dns.rdatatype.NS)
      response = dns.query.udp(query,ns,1)
      if response.rcode() != dns.rcode.NOERROR:
        return False
      if len(response.authority) > 0:
        rrset = response.authority[0]
      else:
        rrset = response.answer[0]
      rr = rrset[0]
      if rr.rdtype == dns.rdatatype.SOA:
        continue
      query = dns.message.make_query(subpart,dns.rdatatype.DNSKEY,want_dnssec=True)
      response = dns.query.udp(query,ns,1)
      if response.rcode() != 0:
        return False
      answer = response.answer
      if len(answer) != 2:
        return False
      name = dns.name.from_text(subpart)
      dns.dnssec.validate(answer[0],answer[1],{name:answer[0]})
      return True
  except Exception,e:
    log_error('Failed to validate DNSSEC for %s: %s' % (address, str(e)))
    return False
예제 #6
0
파일: twitter.py 프로젝트: clintar/tippero
  def _post_next_reply(self):
    data=redis_lindex('twitter:replies',0)
    if not data:
      return False
    parts=data.split(':',2)
    mtype=parts[0]
    data=parts[1]
    text=parts[2]

    try:
      if mtype == 'g':
        log_info('call: update_status(%s,%s)' % (str(text),str(data)))
        self.twitter.update_status(status=text,in_reply_to_status_id=data)
      elif mtype == 'u':
        log_info('call: send_direct_message(%s,%s)' % (str(data),str(text)))
        self.twitter.send_direct_message(user=data,text=text)
      else:
        log_error('Invalid reply type: %s' % str(mtype))
      redis_lpop('twitter:replies')
    except Exception,e:
      log_error('Failed to send reply: %s' % str(e))
      redis_lpop('twitter:replies')
      return True

      return False
예제 #7
0
파일: utils.py 프로젝트: clintar/tippero
def GetPaymentID(link):
  salt="2u3g55bkwrui32fi3g4bGR$j5g4ugnujb-"+coinspecs.name+"-";
  p = hashlib.sha256(salt+link.identity()).hexdigest();
  try:
    redis_hset("paymentid",p,link.identity())
  except Exception,e:
    log_error('GetPaymentID: failed to set payment ID for %s to redis: %s' % (link.identity(),str(e)))
예제 #8
0
파일: twitter.py 프로젝트: clintar/tippero
 def run(self):
   while not self.stop:
     try:
       self._check()
     except Exception,e:
       log_error('Exception in TwitterNetwork:_check: %s' % str(e))
     time.sleep(1)
예제 #9
0
파일: redisdb.py 프로젝트: clintar/tippero
def CompatibilityCheck():
  try:
    r = redis.Redis()
    if not r.pipeline: raise RuntimeError('pipeline call not found')
    p = r.pipeline()
    if not p.exists: raise RuntimeError('exists call not found')
    if not p.get: raise RuntimeError('get call not found')
    if not p.set: raise RuntimeError('set call not found')
    if not p.hexists: raise RuntimeError('hexists call not found')
    if not p.hget: raise RuntimeError('hget call not found')
    if not p.hgetall: raise RuntimeError('hgetall call not found')
    if not p.hset: raise RuntimeError('hset call not found')
    if not p.hincrby: raise RuntimeError('hincrby call not found')
    if not p.hdel: raise RuntimeError('hdel call not found')
    if not p.incrby: raise RuntimeError('incrby call not found')
    if not p.sadd: raise RuntimeError('sadd call not found')
    if not p.smembers: raise RuntimeError('smembers call not found')
    if not p.sismember: raise RuntimeError('sismember call not found')
    if not p.rpush: raise RuntimeError('rpush call not found')
    if not p.lpop: raise RuntimeError('lpop call not found')
    if not p.llen: raise RuntimeError('llen call not found')
    if not p.lindex: raise RuntimeError('lindex call not found')
    if not p.lset: raise RuntimeError('lset call not found')
    if not p.zincrby: raise RuntimeError('zincrby call not found')
    if not p.zscore: raise RuntimeError('zscore call not found')
    if not p.zrangebylex: raise RuntimeError('zrangebylex call not found')
    if not p.keys: raise RuntimeError('keys call not found')
    if not p.execute: raise RuntimeError('execute call not found')
    if not p.delete: raise RuntimeError('delete call not found')
  except Exception,e:
    log_error('Error checking redis compatibility: %s' % str(e))
    exit(1)
예제 #10
0
파일: tipping.py 프로젝트: clintar/tippero
def PerformTip(link,whoid,units):
  identity=link.identity()
  try:
    account = GetAccount(identity)
    who_account = GetAccount(whoid)
    balance = redis_hget("balances",account)
    if balance == None:
      balance = 0
    balance=long(balance)
    if units > balance:
      link.send("You only have %s" % (AmountToString(balance)))
      return
    log_info('Tip: %s tipping %s %u units, with balance %u' % (identity, whoid, units, balance))
    try:
      p = redis_pipeline()
      p.incrby("tips_total_count",1);
      p.incrby("tips_total_amount",units);
      p.hincrby("tips_count",identity,1);
      p.hincrby("tips_amount",identity,units);
      p.hincrby("balances",account,-units);
      p.hincrby("balances",who_account,units)
      p.execute()
      if units < coinspecs.atomic_units:
        link.send("%s has tipped %s %s (%.16g %s)" % (NickFromIdentity(identity), NickFromIdentity(whoid), AmountToString(units), float(units) / coinspecs.atomic_units, coinspecs.name))
      else:
        link.send("%s has tipped %s %s" % (NickFromIdentity(identity), NickFromIdentity(whoid), AmountToString(units)))
    except Exception, e:
      log_error("Tip: Error updating redis: %s" % str(e))
      link.send("An error occured")
      return
  except Exception, e:
    log_error('Tip: exception: %s' % str(e))
    link.send("An error has occured")
예제 #11
0
파일: tipbot.py 프로젝트: clintar/tippero
def GetHeight(link,cmd):
  log_info('GetHeight: %s wants to know block height' % str(link))
  try:
    j = SendDaemonHTMLCommand("getheight")
  except Exception,e:
    log_error('GetHeight: error: %s' % str(e))
    link.send("An error has occured")
    return
예제 #12
0
def FairCheck(link,cmd):
  identity=link.identity()
  try:
    seed = GetServerSeed(link,'blackjack')
  except Exception,e:
    log_error('Failed to get server seed for %s: %s' % (identity,str(e)))
    link.send('An error has occured')
    return
예제 #13
0
파일: irc.py 프로젝트: clintar/tippero
 def get_last_active_time(self,nick,chan):
   if not chan in self.userstable:
     log_error("IRCNetwork:get_last_active_time: channel %s not found in users table" % chan)
     return None
   if not nick in self.userstable[chan]:
     log_error("IRCNetwork:get_last_active_time: %s not found in channel %s's users table" % (nick, chan))
     return None
   return self.userstable[chan][nick]
예제 #14
0
파일: tipbot.py 프로젝트: clintar/tippero
def InitScanBlockHeight():
  try:
    scan_block_height = redis_get("scan_block_height")
    scan_block_height = long(scan_block_height)
  except Exception,e:
    try:
      redis_set("scan_block_height",0)
    except Exception,e:
      log_error('Failed to initialize scan_block_height: %s' % str(e))
예제 #15
0
파일: utils.py 프로젝트: clintar/tippero
def RetrieveBalance(link):
  try:
    account = GetAccount(link)
    balance = redis_hget("balances",account) or 0
    confirming = redis_hget("confirming_payments",account) or 0
    return long(balance), long(confirming)
  except Exception, e:
    log_error('RetrieveBalance: exception: %s' % str(e))
    raise
예제 #16
0
파일: tipbot.py 프로젝트: clintar/tippero
def OnCommandProxy(link,cmd):
  if disabled:
    log_info('Ignoring command from %s while disabled: %s' % (str(link.identity()),str(cmd)))
    return
  link.batch_send_start()
  try:
    OnCommand(link,cmd,RunAdminCommand,RunRegisteredCommand)
  except Exception,e:
    log_error('Exception running command %s: %s' % (str(cmd),str(e)))
예제 #17
0
파일: twitter.py 프로젝트: clintar/tippero
 def _intern(self,contents):
   base=str(time.time())+":"+str(getrandbits(128))+":"
   for n in range(10000):
     filename=hashlib.sha256(base+str(n)).hexdigest()[:self.fs_hash_length]
     split_path=self._check_and_create(filename,contents)
     if split_path:
       return split_path
   log_error('Failed to intern contents')
   return None
예제 #18
0
파일: dice.py 프로젝트: clintar/tippero
def Seeds(link,cmd):
  identity=link.identity()
  try:
    sh = GetServerSeedHash(link,'dice')
    ps = GetPlayerSeed(link,'dice')
  except Exception,e:
    log_error('Failed to get server seed for %s: %s' % (identity,str(e)))
    link.send('An error has occured')
    return
예제 #19
0
파일: redisdb.py 프로젝트: clintar/tippero
def connect_to_redis(host,port):
  log_info('Connecting to Redis at %s:%u' % (host, port))
  try:
    global redisdb
    redisdb = redis.Redis(host=host,port=port)
    return redisdb
  except Exception, e:
    log_error( 'Error initializing redis: %s' % str(e))
    exit()
예제 #20
0
파일: irc.py 프로젝트: clintar/tippero
 def update_last_active_time(self,chan,nick):
   if chan[0] != '#':
     return
   if not chan in self.userstable:
     log_error("IRCNetwork:update_last_active_time: %s spoke in %s, but %s not found in users table" % (nick, chan, chan))
     self.userstable[chan] = dict()
   if not nick in self.userstable[chan]:
     log_error("IRCNetwork:update_last_active_time: %s spoke in %s, but was not found in that channel's users table" % (nick, chan))
     self.userstable[chan][nick] = None
   self.userstable[chan][nick] = time.time()
예제 #21
0
파일: dice.py 프로젝트: clintar/tippero
def Roll(link):
  identity=link.identity()
  try:
    if redis_hexists('dice:rolls',identity):
      rolls = redis_hget('dice:rolls',identity)
      rolls = long(rolls) + 1
    else:
      rolls = 1
  except Exception,e:
    log_error('Failed to prepare roll for %s: %s' % (identity, str(e)))
    raise
예제 #22
0
def PlayerSeed(link,cmd):
  identity=link.identity()
  fair_string = GetParam(cmd,1)
  if not fair_string:
    link.send("Usage: !playerseed <string>")
    return
  try:
    SetPlayerSeed(link,'blackjack',fair_string)
  except Exception,e:
    log_error('Failed to save player seed for %s: %s' % (identity, str(e)))
    link.send('An error occured')
예제 #23
0
def GetNewShuffleSeed(link):
  identity=link.identity()
  try:
    if redis_hexists('blackjack:rolls',identity):
      rolls = redis_hget('blackjack:rolls',identity)
      rolls = long(rolls) + 1
    else:
      rolls = 1
  except Exception,e:
    log_error('Failed to prepare roll for %s: %s' % (identity, str(e)))
    raise
예제 #24
0
파일: bookie.py 프로젝트: clintar/tippero
def Result(link,cmd):
  identity=link.identity()

  SweepClosingTimes()

  res0, res1 = GetBookIndex(cmd,1)
  if res0 == None:
    link.send(res1)
    return
  book_index = res0
  parm_offset = res1

  tname = "bookie:%d" % book_index
  book_name=redis_hget(tname,'name')

  outcome = GetParam(cmd,1+parm_offset)
  if not outcome:
    link.send('usage: !result [<event name>] <outcome>')
    return
  outcomes = redis_smembers(tname+':outcomes')
  if not outcome in outcomes:
    link.send("%s is not a valid outcome for %s, try one of: %s" % (outcome, book_name, ", ".join(outcomes)))
    return

  log_info('%s calls %s on book %d' % (identity, outcome, book_index))
  try:
    p = redis_pipeline()
    total_units_bet = long(redis_hget(tname,"bets") or 0)
    total_units_bet_by_winners = long(redis_hget(tname+":bets",outcome) or 0)
    resultmsg = []
    bettors = redis_smembers(tname+':bettors')
    p.hincrby("earmarked","bookie",-total_units_bet)
    for bettor in bettors:
      o = redis_hget(tname,bettor+":outcome")
      ounits = long(redis_hget(tname,bettor+":units"))
      if o == outcome:
        a = GetAccount(bettor)
        owinunits = long(total_units_bet * (1-config.bookie_fee) * ounits / total_units_bet_by_winners)
        if owinunits<ounits:
          owinunits=ounits
        resultmsg.append("%s wins %s" % (NickFromIdentity(bettor), AmountToString(owinunits)))
        p.hincrby("balances",a,owinunits)
      else:
        resultmsg.append("%s loses %s" % (NickFromIdentity(bettor), AmountToString(ounits)))
    p.hdel('bookie:active',book_index)
    p.execute()
    if len(bettors) == 0:
      resultmsg = ["nobody had bet"]
    log_info('Book outcome is %s - %s' % (outcome, ", ".join(resultmsg)))
    link.send('Book #%d (%s) outcome is %s - %s' % (book_index, book_name, outcome, ", ".join(resultmsg)))
  except Exception,e:
    log_error('Result: Failed to process result: %s' % str(e))
    link.send('An error occured')
    return
예제 #25
0
파일: utils.py 프로젝트: clintar/tippero
def GetPassword(name):
  try:
    f = open('tipbot-password.txt', 'r')
    for p in f:
      p = p.strip("\r\n")
      parts=p.split(':')
      if parts[0]==name:
        return parts[1]
  except Exception,e:
    log_error('could not fetch password: %s' % str(e))
    raise
    return "xxx"
예제 #26
0
파일: tipbot.py 프로젝트: clintar/tippero
def OnEventProxy(event,*args,**kwargs):
  log_info('Got event %s, args %s' % (event, str(kwargs)))
  if disabled:
    log_info('Ignoring event while disabled')
    return
  link=kwargs['link'] if 'link' in kwargs else None
  if link:
    link.batch_send_start()
  try:
    OnEvent(event,*args,**kwargs)
  except Exception,e:
    log_error('Exception handling event %s: %s' % (str(event),str(e)))
예제 #27
0
파일: utils.py 프로젝트: clintar/tippero
def IdentityFromString(link,s):
  if s.find(':') == -1:
    network = link.network
    nick=s
  else:
    parts=s.split(':')
    network_name=parts[0]
    network=GetNetworkByName(network_name)
    if not network:
      log_error('unknown network: %s' % network_name)
      raise RuntimeError('Unknown network: %s' % network_name)
    nick=parts[1]
  return network.name+':'+network.canonicalize(nick)
예제 #28
0
def RecordMove(link,actual):
  identity=link.identity()
  basic = GetBasicStrategyMove(link)
  log_info('%s %ss, basic strategy would %s' % (identity, actual, basic))
  try:
    p = redis_pipeline()
    tname="blackjack:strategy:"+identity
    alltname="blackjack:strategy:"
    p.hincrby(tname,"moves",1)
    if actual == basic:
      p.hincrby(tname,"matching",1)
    p.execute()
  except Exception,e:
    log_error('Failed to record move for %s: %s' % (identity, str(e)))
예제 #29
0
파일: utils.py 프로젝트: clintar/tippero
def RetrieveTipbotBalance(force_refresh=False):
  global cached_tipbot_balance, cached_tipbot_unlocked_balance, cached_tipbot_balance_timestamp
  if not force_refresh and cached_tipbot_balance_timestamp and time.time()-cached_tipbot_balance_timestamp < config.tipbot_balance_cache_time:
    return cached_tipbot_balance, cached_tipbot_unlocked_balance

  j = SendWalletJSONRPCCommand("getbalance",None)
  if not "result" in j:
    log_error('RetrieveTipbotBalance: result not found in reply')
    raise RuntimeError("")
    return
  result = j["result"]
  if not "balance" in result:
    log_error('RetrieveTipbotBalance: balance not found in result')
    raise RuntimeError("")
    return
  if not "unlocked_balance" in result:
    log_error('RetrieveTipbotBalance: unlocked_balance not found in result')
    raise RuntimeError("")
    return
  balance = result["balance"]
  unlocked_balance = result["unlocked_balance"]
  log_log('RetrieveTipbotBalance: balance: %s' % str(balance))
  log_log('RetrieveTipbotBalance: unlocked_balance: %s' % str(unlocked_balance))
  pending = long(balance)-long(unlocked_balance)
  if pending < 0:
    log_error('RetrieveTipbotBalance: Negative pending balance! balance %s, unlocked %s' % (str(balance),str(unlocked_balance)))
    raise RuntimeError("")
    return
  cached_tipbot_balance_timestamp=time.time()
  cached_tipbot_balance=balance
  cached_tipbot_unlocked_balance=unlocked_balance
  return balance, unlocked_balance
예제 #30
0
def GetBlackjackStats(link,cmd):
  identity=link.identity()
  sidentity = GetParam(cmd,1)
  if sidentity:
    sidentity=IdentityFromString(link,sidentity)
  if sidentity and sidentity != identity:
    if not IsAdmin(link):
      log_error('%s is not admin, cannot see blackjack stats for %s' % (identity, sidentity))
      link.send('Access denied')
      return
  else:
    sidentity=identity
  ShowBlackjackStats(link,sidentity,NickFromIdentity(sidentity))
  ShowBlackjackStats(link,"reset:"+sidentity,'%s since reset' % NickFromIdentity(sidentity))
  ShowBlackjackStats(link,'','overall')
예제 #31
0
 def _schedule_tweet(self, msg, reply_to_msg):
     try:
         log_info('Scheduling tweet in reply to %s: %s' %
                  (str(reply_to_msg.id), msg))
         if self.uri_base:
             name = self.canonicalize(reply_to_msg.user.screen_name)
             msg = "%s: %s" % (name, msg)
             if self._can_be_sent_raw(msg):
                 redis_sadd('twitter:message_hashes',
                            hashlib.sha256(msg).hexdigest())
             else:
                 uri = self._make_uri(msg)
                 msg = "%s: %s%s" % (name, self.prefix_when_linked, uri)
         reply = "g:" + str(reply_to_msg.id) + ":" + msg
         redis_rpush('twitter:replies', reply)
     except Exception, e:
         log_error('Error scheduling tweet: %s' % str(e))
예제 #32
0
def AddBalance(link, cmd):
    nick = link.user.nick
    if GetParam(cmd, 2):
        anick = GetParam(cmd, 1)
        amount = GetParam(cmd, 2)
    else:
        anick = nick
        amount = GetParam(cmd, 1)
    if not amount:
        link.send('usage: !addbalance [<nick>] <amount>')
        return
    try:
        units = StringToUnits(amount)
    except Exception, e:
        log_error('AddBalance: error converting amount: %s' % str(e))
        link.send('usage: !addbalance [<nick>] <amount>')
        return
예제 #33
0
def ResetKitsuneStats(link, cmd):
    identity = link.identity()
    sidentity = GetParam(cmd, 1)
    if sidentity:
        sidentity = IdentityFromString(link, sidentity)
    if sidentity and sidentity != identity:
        if not IsAdmin(link):
            log_error('%s is not admin, cannot see kitsune stats for %s' %
                      (identity, sidentity))
            link.send('Access denied')
            return
    else:
        sidentity = identity
    try:
        ResetGameStats(link, sidentity, "kitsune")
    except Exception, e:
        link.send("An error occured")
예제 #34
0
def GetKitsuneStats(link, cmd):
    identity = link.identity()
    sidentity = GetParam(cmd, 1)
    if sidentity:
        sidentity = IdentityFromString(link, sidentity)
    if sidentity and sidentity != identity:
        if not IsAdmin(link):
            log_error('%s is not admin, cannot see kitsune stats for %s' %
                      (identity, sidentity))
            link.send('Access denied')
            return
    else:
        sidentity = identity
    ShowKitsuneStats(link, sidentity, NickFromIdentity(sidentity))
    ShowKitsuneStats(link, "reset:" + sidentity,
                     '%s since reset' % NickFromIdentity(sidentity))
    ShowKitsuneStats(link, '', 'overall')
예제 #35
0
def Load(link, cmd):
    modulename = GetParam(cmd, 1)
    if not modulename:
        link.send("Usage: load <modulename>")
        return
    if modulename == "builtin":
        link.send("Cannot load builtin module")
        return
    if modulename in sys.modules:
        link.send("There is already a %s module" % modulename)
        return
    log_info('Loading %s module' % modulename)
    try:
        __import__(modulename)
        link.send('%s loaded' % modulename)
    except Exception, e:
        log_error('Failed to load module "%s": %s' % (modulename, str(e)))
        link.send('An error occured')
예제 #36
0
 def get_active_users(self, seconds, chan):
     nicks = []
     if not chan in self.userstable:
         return []
     now = time.time()
     for nick in self.userstable[chan]:
         t = self.userstable[chan][nick]
         if t == None:
             continue
         dt = now - t
         if dt < 0:
             log_error(
                 "IRCNetwork:get_active_users: %s active in %s in the future"
                 % (nick, chan))
             continue
         if dt < seconds:
             nicks.append(Link(self, User(self, nick), Group(self, chan)))
     return nicks
예제 #37
0
파일: utils.py 프로젝트: selsta/tippero
def LinkCore(link, other_identity):
    try:
        identity = link.identity()
        if identity == other_identity:
            return True, "same-identity"
        links = redis_hget('links', identity)
        if links:
            if other_identity in links.split(chr(0)):
                return True, "already"
            links = links + chr(0) + other_identity
        else:
            links = other_identity
        redis_hset('links', identity, links)

        links = redis_hget('links', other_identity)
        if links:
            if identity in links.split(chr(0)):
                # we have both
                account = GetAccount(identity)
                other_account = GetAccount(other_identity)
                if account == other_account:
                    log_info('%s and %s already have the same account: %s' %
                             (identity, other_identity, account))
                    return True, "same-account"

                balance = long(redis_hget('balances', account))
                log_info('Linking accounts %s (%s) and %s (%s)' %
                         (account, identity, other_account, other_identity))
                p = redis_pipeline()
                p.hincrby('balances', other_account, balance)
                p.hincrby('balances', account, -balance)
                accounts = redis_hgetall('accounts')
                for a in accounts:
                    if accounts[a] == account:
                        log_info('Changing %s\'s account from %s to %s' %
                                 (a, account, other_account))
                        p.hset('accounts', a, other_account)
                p.execute()
                return True, "linked"
    except Exception, e:
        log_error('Error linking %s and %s: %s' %
                  (identity, other_identity, str(e)))
        return False, "error"
예제 #38
0
 def connect(self):
     try:
         cfg = config.network_config[self.name]
         host = cfg['host']
         port = cfg['port']
         login = cfg['login']
         password = GetPassword(self.name)
         delay = cfg['delay']
         self.use_ssl = cfg['ssl']
         self.use_sasl = cfg['sasl']
         self.welcome_line = cfg['welcome_line']
         self.timeout_seconds = cfg['timeout_seconds']
         self.channels = cfg['channels']
         if self.use_sasl:
             self.sasl_name = cfg['sasl_name']
     except Exception, e:
         log_error('Configuration not found for %s: %s' %
                   (self.name, str(e)))
         return False
예제 #39
0
def Unload(link, cmd):
    modulename = GetParam(cmd, 1)
    if not modulename:
        link.send("Usage: unload <modulename>")
        return
    if modulename == "builtin":
        link.send("Cannot unload builtin module")
        return
    if not modulename in sys.modules:
        link.send("%s is not a dynamic module" % modulename)
        return
    log_info('Unloading %s module' % modulename)
    UnregisterModule(modulename)
    try:
        del sys.modules[modulename]
        link.send('%s unloaded' % modulename)
    except Exception, e:
        log_error('Failed to unload module "%s": %s' % (modulename, str(e)))
        link.send('An error occured')
예제 #40
0
    def connect(self):
        if self.thread:
            return False
        try:
            cfg = config.network_config[self.name]
            self.login = cfg['login']
            ckey = GetPassword(self.name + "/ckey")
            csecret = GetPassword(self.name + "/csecret")
            atoken = GetPassword(self.name + "/atoken")
            atsecret = GetPassword(self.name + "/atsecret")
            self.update_period = cfg['update_period']
            self.keyword = cfg['keyword'].lower()
            self.fs_location = cfg['fs_location']
            self.fs_prefix_tree = cfg['fs_prefix_tree']
            self.uri_base = cfg['uri_base']
            self.prefix_when_linked = cfg['prefix_when_linked']
            self.fs_hash_length = cfg['fs_hash_length']

            if self.fs_location and not self._is_valid_location(
                    self.fs_location):
                log_error('Invalid location: %s' % self.fs_location)
                return False

            self.items_cache = dict()
            self.last_seen_tweet_id = long(
                redis_get('twitter:last_seen_tweet_id') or 0)
            self.last_seen_dm_id = long(
                redis_get('twitter:last_seen_dm_id') or 0)
            log_log('loaded last seen id: tweet %s, dm %s' %
                    (str(self.last_seen_tweet_id), str(self.last_seen_dm_id)))

            auth = tweepy.OAuthHandler(ckey, csecret)
            auth.set_access_token(atoken, atsecret)
            self.twitter = tweepy.API(auth)

            self.stop = False
            self.thread = threading.Thread(target=self.run)
            self.thread.start()

        except Exception, e:
            log_error('Failed to login to twitter: %s' % str(e))
            return False
예제 #41
0
def Book(link, cmd):
    identity = link.identity()

    SweepClosingTimes()

    active_books = GetActiveBooks()
    if len(active_books) == 0:
        link.send('The book is empty')
        return

    for book_index in sorted(active_books.keys()):
        book_index = long(book_index)
        tname = 'bookie:%s' % book_index
        try:
            name = redis_hget(tname, 'name')
            outcomes = redis_smembers(tname + ':outcomes')
            outcome = redis_hget(tname, identity + ":outcome")
            units = redis_hget(tname, identity + ":units")
        except Exception, e:
            log_error('Book: Failed to retrieve book %d: %s' %
                      (book_index, str(e)))
            link.send('An error occured')
            return
        outcomes = redis_smembers(tname + ':outcomes')
        outcomes_with_bets = []
        for o in outcomes:
            ou = long(redis_hget(tname + ":bets", o) or 0)
            if ou > 0:
                outcomes_with_bets.append(o + " (%s)" % AmountToString(ou))
            else:
                outcomes_with_bets.append(o)
        msg = 'Book #%d (%s): %s' % (book_index, name,
                                     ", ".join(outcomes_with_bets))
        if redis_hget(tname, 'closed'):
            msg = msg + " - closed"
        elif redis_hexists(tname, 'closing_time'):
            try:
                closing_time = float(redis_hget(tname, 'closing_time'))
                msg = msg + ' - closing in %s' % (TimeToString(closing_time -
                                                               time.time()))
            except Exception, e:
                log_error('Failed to get closing time: %s' % (str(e)))
예제 #42
0
  def _post_next_reply(self):
    data=redis_lindex('reddit:replies',0)
    if not data:
      return False
    parts=data.split(':',2)
    fullname=parts[0]
    recipient=parts[1]
    text=parts[2]

    text = text.replace('\n\n','\n\n  &nbsp;  \n\n').replace('\n','  \n')

    try:
      if recipient:
        # PM
        self.reddit.send_message(recipient,"Reply from %s"%self.login,text,raise_captcha_exception=True)
        log_info('Posted message to %s: %s' % (recipient,text))
      else:
        # subreddit or reply to PM
        item = None
        log_info('looking for "%s" in %s' % (str(fullname),str(self.items_cache)))
        if fullname in self.items_cache:
          item=self.items_cache[fullname]
        if not item:
          item = self.reddit.message(fullname)
        if not item:
          gen=self.reddit.info([fullname])
          item=next(gen, None)
        if not item:
          log_error('Failed to find item %s to post %s' % (fullname,text))
          redis_lpop('reddit:replies')
          return True
        reply_item=item.reply(text)
        log_info('Posted reply to %s: %s' % (fullname,text))
        if reply_item and hasattr(reply_item,'id'):
          redis_sadd('reddit:last_seen_ids',reply_item.id)

      redis_lpop('reddit:replies')

    except Exception,e:
      log_error('Error sending %s, will retry: %s' % (data,str(e)))
      return False
예제 #43
0
    def connect(self):
        if self.thread:
            return False
        try:
            cfg = config.network_config[self.name]
            self.login = cfg['login']
            password = GetPassword(self.name + '/password')
            self.subreddits = cfg['subreddits']
            user_agent = cfg['user_agent']
            self.update_period = cfg['update_period']
            self.load_limit = cfg['load_limit']
            self.keyword = cfg['keyword']
            self.use_unread_api = cfg['use_unread_api']
            self.cache_timeout = cfg['cache_timeout']
            client_id = GetPassword(self.name + '/client_id')
            client_secret = GetPassword(self.name + '/client_secret')
            username = GetPassword(self.name + '/username')

            if False:
                handler = logging.StreamHandler()
                handler.setLevel(logging.DEBUG)
                logger = logging.getLogger('prawcore')
                logger.setLevel(logging.DEBUG)
                logger.addHandler(handler)

            self.reddit = praw.Reddit(client_id=client_id,
                                      client_secret=client_secret,
                                      password=password,
                                      user_agent=user_agent,
                                      username=username)
            log_info("Logged in reddit as " + str(self.reddit.user.me()))
            self.items_cache = dict()

            self.stop = False
            self.thread = threading.Thread(target=self.run)
            self.thread.start()
            self.logged_in = True

        except Exception, e:
            log_error('Failed to login to reddit: %s' % str(e))
            return False
예제 #44
0
def ScheduleClose(link, cmd):
    identity = link.identity()

    SweepClosingTimes()

    res0, res1 = GetBookIndex(cmd, 0)
    if res0 == None:
        link.send(res1)
        return
    book_index = res0
    parm_offset = res1

    tname = "bookie:%d" % book_index
    book_name = redis_hget(tname, 'name')

    try:
        minutes = float(GetParam(cmd, 1 + parm_offset))
    except Exception, e:
        log_error('error getting minutes: %s' % str(e))
        link.send('usage: schedule_close [<event name>] <minutes>')
        return
예제 #45
0
 def _check_and_create(self, filename, contents):
     if len(filename) <= self.fs_prefix_tree:
         log_error('Filename %s too small for prefix tree %d' %
                   (filename, self.fs_prefix_tree))
         return None
     path = self.fs_location
     split_path = ''
     for p in range(self.fs_prefix_tree):
         path = os.path.join(path, filename[p])
         split_path = '/'.join([split_path, filename[p]])
         if os.path.exists(path):
             if not os.path.isdir(path):
                 log_log('notadir')
                 log_error('%s exists and is not a directory' % str(path))
                 return None
         else:
             os.mkdir(path)
     fpath = os.path.join(path, filename[self.fs_prefix_tree:])
     split_path = '/'.join([split_path, filename[self.fs_prefix_tree:]])
     if os.path.exists(fpath):
         log_error('%s exists' % str(fpath))
         return None
     f = open(fpath, 'w')
     f.write(contents)
     f.close()
     return split_path
예제 #46
0
def Close(link, cmd):
    identity = link.identity()

    SweepClosingTimes()

    res0, res1 = GetBookIndex(cmd, 0)
    if res0 == None:
        link.send(res1)
        return
    book_index = res0
    parm_offset = res1

    tname = "bookie:%d" % book_index
    book_name = redis_hget(tname, 'name')

    log_info('Closing book %d' % book_index)
    try:
        redis_hset(tname, 'closed', 1)
    except Exception, e:
        log_error('Failed to close book: %s' % str(e))
        link.send('An error occured')
        return
예제 #47
0
 def on_notice(self,who,text):
   if who == "NickServ!NickServ@services.":
     if text.find(' ACC ') != -1:
       stext  = text.split(' ')
       ns_nick = stext[0]
       ns_acc = stext[1]
       ns_status = stext[2]
       if ns_acc == "ACC":
         ns_link=Link(self,User(self,ns_nick),None)
         if ns_status == "3":
           log_info('NickServ says %s is identified' % ns_nick)
           self.registered_users.add(ns_link.identity())
           if self.on_identified:
             self.on_identified(ns_link,True)
         else:
           log_info('NickServ says %s is not identified' % ns_nick)
           self.registered_users.discard(ns_link.identity())
           if self.on_identified:
             self.on_identified(ns_link,False)
       else:
         log_error('ACC line not as expected...')
   return True
예제 #48
0
    def _parse_tweet(self, msg):
        if msg.user.screen_name.lower() == self.login.lower(
        ) and not force_parse_self:
            log_log('Ignoring tweet from self')
            return

        log_info('Twitter: parsing tweet from %s: %s' %
                 (msg.user.screen_name, msg.text))

        # twitter special: +x means tip the user mentioned with a @
        for line in msg.text.split('\n'):
            line = line.lower()
            line = line.replace(self.keyword, '', 1).strip()
            log_log('After removal: %s' % line)
            if re.match(username_regexp + "[ \t]*" + amount_regexp,
                        line) or re.match(
                            amount_regexp + "[ \t]*" + username_regexp, line):
                link = Link(self, User(self, msg.user.screen_name), None, msg)
                match = re.search(username_regexp, line)
                if not match:
                    continue
                target = match.group(0)
                match = re.search(amount_regexp,
                                  line.replace(target, '').strip())
                if not match:
                    continue
                amount = match.group(0)
                if self.on_command:
                    try:
                        synthetic_cmd = [
                            'tip',
                            target.replace('@', '').strip(),
                            amount.replace('+', '').strip()
                        ]
                        log_log('Running synthetic command: %s' %
                                (str(synthetic_cmd)))
                        self.on_command(link, synthetic_cmd)
                    except Exception, e:
                        log_error('Failed to tip %s: %s' % (target, str(e)))
예제 #49
0
파일: payment.py 프로젝트: selsta/tippero
def UpdateCoin(data):
    global last_wallet_update_time
    if last_wallet_update_time == None:
        last_wallet_update_time = 0
    t = time.time()
    dt = t - last_wallet_update_time
    if dt < config.wallet_update_time:
        return
    try:
        try:
            scan_block_height = redis_get("scan_block_height")
            scan_block_height = long(scan_block_height)
        except Exception, e:
            log_error('Failed to get scan_block_height: %s' % str(e))
            last_wallet_update_time = time.time()
            return

        try:
            j = SendDaemonHTMLCommand("getheight")
        except Exception, e:
            log_error('UpdateCoin: error getting height: %s' % str(e))
            return
예제 #50
0
def PerformTip(link, whoid, units):
    identity = link.identity()
    try:
        account = GetAccount(identity)
        who_account = GetAccount(whoid)
        balance = redis_hget("balances", account)
        if balance == None:
            balance = 0
        balance = long(balance)
        if units > balance:
            link.send("You only have %s" % (AmountToString(balance)))
            return
        log_info('Tip: %s tipping %s %u units, with balance %u' %
                 (identity, whoid, units, balance))
        try:
            p = redis_pipeline()
            p.incrby("tips_total_count", 1)
            p.incrby("tips_total_amount", units)
            p.hincrby("tips_count", identity, 1)
            p.hincrby("tips_amount", identity, units)
            p.hincrby("balances", account, -units)
            p.hincrby("balances", who_account, units)
            p.execute()
            if units < coinspecs.atomic_units:
                link.send("%s has tipped %s %s (%.16g %s)" %
                          (NickFromIdentity(identity), NickFromIdentity(whoid),
                           AmountToString(units), float(units) /
                           coinspecs.atomic_units, coinspecs.name))
            else:
                link.send("%s has tipped %s %s" %
                          (NickFromIdentity(identity), NickFromIdentity(whoid),
                           AmountToString(units)))
        except Exception, e:
            log_error("Tip: Error updating redis: %s" % str(e))
            link.send("An error occured")
            return
    except Exception, e:
        log_error('Tip: exception: %s' % str(e))
        link.send("An error has occured")
예제 #51
0
def Cancel(link, cmd):
    identity = link.identity()

    SweepClosingTimes()

    res0, res1 = GetBookIndex(cmd, 0)
    if res0 == None:
        link.send(res1)
        return
    book_index = res0
    parm_offset = res1

    tname = 'bookie:%d' % book_index
    book_name = redis_hget(tname, 'name')

    log_info('Cancelling book %d (%s)' % (book_index, book_name))
    try:
        p = redis_pipeline()
        bettors = redis_smembers(tname + ':bettors')
        refundmsg = []
        for bettor in bettors:
            units = long(redis_hget(tname, bettor + ":units"))
            log_info('Refunding %s to %s' % (AmountToString(units), bettor))
            a = GetAccount(bettor)
            p.hincrby('balances', a, units)
            p.hincrby('earmarked', 'bookie', -units)
            refundmsg.append('%s to %s' %
                             (AmountToString(units), NickFromIdentity(bettor)))
        p.hdel('bookie:active', book_index)
        p.execute()
        if len(refundmsg) == 0:
            link.send('Book %s cancelled, nobody had bet' % book_name)
        else:
            link.send('Book %s cancelled, refunding %s' %
                      (book_name, ", ".join(refundmsg)))
    except Exception, e:
        log_error('Cancel: Failed to cancel book: %s' % str(e))
        link.send('Failed to cancel book %s' % book_name)
        return
예제 #52
0
 def _getline(self):
     idx = self.buffered_data.find("\n")
     if idx == -1:
         try:
             (r, w, x) = select.select([self.irc.fileno()], [], [], 1)
             if self.irc.fileno() in r:
                 newdata = self._irc_recv(4096, socket.MSG_DONTWAIT)
                 if len(newdata) == 0:
                     raise RuntimeError('0 bytes received, EOF')
             else:
                 newdata = None
             if self.irc.fileno() in x:
                 log_error('getline: IRC socket in exception set')
                 newdata = None
         except Exception, e:
             log_error('getline: Exception: %s' % str(e))
             # Broken pipe when we get kicked for spam
             if str(e).find("Broken pipe") != -1:
                 raise
             newdata = None
         if newdata == None:
             return None
         self.buffered_data += newdata
예제 #53
0
def ResolveCore(address, ctype):
    log_info('Resolving %s address for %s' % (ctype, address))
    address = address.replace('@', '.')
    if not '.' in address:
        return False, 'invalid address'

    try:
        for attempt in range(3):
            resolver = dns.resolver.Resolver()
            resolver.timeout = 2
            resolver.lifetime = 2
            records = resolver.query(address, dns.rdatatype.TXT)
            for record in records:
                s = record.strings[0]
                if s.lower().startswith('oa1:%s' % ctype.lower()):
                    a = re.sub(
                        '.*recipient_address[ \t]*=[ \t]*\"?([A-Za-z0-9]+)\"?.*',
                        '\\1', s)
                    if IsValidAddress(a):
                        log_info('Found %s address at %s: %s' %
                                 (ctype, address, a))
                        return True, [a, ValidateDNSSEC(address)]
    except Exception, e:
        log_error('Error resolving %s: %s' % (address, str(e)))
예제 #54
0
def GetBalance(link, cmd):
    nick = link.user.nick
    if link.group and nick.startswith('blackbab'):
        link.send_private("Stop spamming the public channel")
        return
    try:
        balance, confirming = RetrieveBalance(link)
        sbalance = AmountToString(balance)
        if balance < coinspecs.atomic_units:
            if balance == 0:
                msg = "%s's balance is %s" % (nick, sbalance)
            else:
                msg = "%s's balance is %s (%.16g %s)" % (
                    nick, sbalance, float(balance) / coinspecs.atomic_units,
                    coinspecs.name)
        else:
            msg = "%s's balance is %s" % (nick, sbalance)
        if confirming > 0:
            msg = msg + " (%s awaiting confirmation)" % (
                AmountToString(confirming))
        link.send(msg)
    except Exception, e:
        log_error('GetBalance: exception: %s' % str(e))
        link.send("An error has occured")
예제 #55
0
 def _is_valid_location(self, location):
     try:
         path = os.path.abspath(location)
         if not os.path.exists(path):
             log_error('Path %s does not exist' % str(path))
             return False
         if not os.path.isdir(path):
             log_error('%s is not a directory' % str(path))
             return False
         return True
     except Exception, e:
         log_error('Error checking path %s: %s' % (str(location), str(e)))
         return False
예제 #56
0
파일: payment.py 프로젝트: selsta/tippero
def GetTipbotAddress():
    try:
        j = SendWalletJSONRPCCommand("getaddress", None)
        if not "result" in j:
            log_error('GetTipbotAddress: No result found in getaddress reply')
            return None
        result = j["result"]
        if not "address" in result:
            log_error('GetTipbotAddress: No address found in getaddress reply')
            return None
        return result["address"]
    except Exception, e:
        log_error("GetTipbotAddress: Error retrieving %s's address: %s" %
                  (config.tipbot_name, str(e)))
        return None
예제 #57
0
파일: utils.py 프로젝트: selsta/tippero
def RetrieveTipbotBalance(force_refresh=False):
    global cached_tipbot_balance, cached_tipbot_unlocked_balance, cached_tipbot_balance_timestamp
    if not force_refresh and cached_tipbot_balance_timestamp and time.time(
    ) - cached_tipbot_balance_timestamp < config.tipbot_balance_cache_time:
        return cached_tipbot_balance, cached_tipbot_unlocked_balance

    j = SendWalletJSONRPCCommand("getbalance", None)
    if not "result" in j:
        log_error('RetrieveTipbotBalance: result not found in reply')
        raise RuntimeError("")
        return
    result = j["result"]
    if not "balance" in result:
        log_error('RetrieveTipbotBalance: balance not found in result')
        raise RuntimeError("")
        return
    if not "unlocked_balance" in result:
        log_error(
            'RetrieveTipbotBalance: unlocked_balance not found in result')
        raise RuntimeError("")
        return
    balance = result["balance"]
    unlocked_balance = result["unlocked_balance"]
    log_log('RetrieveTipbotBalance: balance: %s' % str(balance))
    log_log('RetrieveTipbotBalance: unlocked_balance: %s' %
            str(unlocked_balance))
    pending = long(balance) - long(unlocked_balance)
    if pending < 0:
        log_error(
            'RetrieveTipbotBalance: Negative pending balance! balance %s, unlocked %s'
            % (str(balance), str(unlocked_balance)))
        raise RuntimeError("")
        return
    cached_tipbot_balance_timestamp = time.time()
    cached_tipbot_balance = balance
    cached_tipbot_unlocked_balance = unlocked_balance
    return balance, unlocked_balance
예제 #58
0
        pipe = redis_pipeline()
        pipe.hincrby("balances", account, -units)
        pipe.incrby("rain_total_count", 1)
        pipe.incrby("rain_total_amount", units)
        pipe.hincrby("rain_count", identity, 1)
        pipe.hincrby("rain_amount", identity, units)
        for user in userlist:
            a = GetAccount(user)
            pipe.hincrby("balances", a, user_units)
            if enumerate_users:
                msg = msg + " " + NickFromIdentity(user.identity())
        pipe.execute()
        link.send("%s" % msg)

    except Exception, e:
        log_error('Rain: exception: %s' % str(e))
        link.send("An error has occured")
        return


def RainActive(link, cmd):
    identity = link.identity()

    amount = GetParam(cmd, 1)
    hours = GetParam(cmd, 2)
    minfrac = GetParam(cmd, 3)

    group = link.group
    if not group:
        link.send("Raining can only be done in a channel")
        return
예제 #59
0
from tipbot.utils import *
from tipbot.redisdb import *
from tipbot.command_manager import *

disabled = False

selected_coin = None
modulenames = []
start_networks = []
argc = 1
while argc < len(sys.argv):
    arg = sys.argv[argc]
    if arg == "-c" or arg == "--coin":
        if argc + 1 == len(sys.argv):
            log_error(
                'Usage: tipbot.py [-h|--help] [-m|--module modulename]* -c|--coin <coinname>'
            )
            exit(1)
        argc = argc + 1
        selected_coin = sys.argv[argc]
        try:
            log_info('Importing %s coin setup' % selected_coin)
            if not selected_coin in coinspecs.coinspecs:
                log_error('Unknown coin: %s' % selected_coin)
                exit(1)
            for field in coinspecs.coinspecs[selected_coin]:
                setattr(coinspecs, field,
                        coinspecs.coinspecs[selected_coin][field])
        except Exception, e:
            log_error('Failed to load coin setup for %s: %s' %
                      (selected_coin, str(e)))
예제 #60
0
    except Exception, e:
        link.send("Usage: !pinata <amount>")
        return
    if aim < min_target:
        link.send("The pinata can only be hit by at least %s" %
                  AmountToString(min_target))
        return
    if aim > max_target:
        link.send("The pinata can only be hit by at most %s" %
                  AmountToString(max_target))
        return

    try:
        target = long(redis_hget('pinata', 'target'))
    except Exception, e:
        log_error('Failed to get pinata target: %s' % str(e))
        link.send('An error occured')
        return

    if target < min_target or target > max_target:
        log_error('Pinata target out of range: %s' % target)
        link.send('An error occured')
        return

    account = GetAccount(identity)
    log_info(
        "Pinata: %s wants to swing %s at the pinata, aim is %d, target is %d" %
        (identity, amount, aim, target))
    valid, reason = IsBetValid(link, amount, None, None, 0, 0, 0)
    if not valid:
        log_info("Pinata: %s's bet refused: %s" % (identity, reason))