Ejemplo n.º 1
0
    def notify_tx(cursor: sqlite3.Cursor, txid: str) -> None:
        cursor.execute('select * from notified_tx where txid == ?', (txid, ))

        if cursor.fetchone() is not None:
            return

        try:
            result = coinrpc.call('decoderawtransaction',
                                  coinrpc.call('getrawtransaction', txid))

        except:
            result = None

        if result is None:
            cursor.execute(
                'insert into notified_tx(txid, time, confirmed) values(?, ?, ?)',
                (txid, int(time.time()), -1))
            return

        account_found = False

        for vout in result.get('vout'):
            for address in vout.get('scriptPubKey').get('addresses'):
                cursor.execute(
                    'select account from account_address where address == ?',
                    (address, ))
                account = cursor.fetchone()

                if account is None:
                    continue

                account_found = True

                account = account[0]
                value = vout.get('value')

                cursor.execute(
                    'insert into notified_tx(txid, time, account, value) values(?, ?, ?, ?)',
                    (txid, int(time.time()), account, value))
                continue

        if not account_found:
            cursor.execute(
                'insert into notified_tx(txid, time, confirmed) values(?, ?, ?)',
                (txid, int(time.time()), 2))
Ejemplo n.º 2
0
    def exec_withdrawal(cursor: sqlite3.Cursor) -> None:
        cursor.execute(
            'select address from withdrawal_req where completed == 0')
        addresses = {r[0] for r in cursor.fetchall()}

        if len(addresses) == 0:
            return

        params = {}

        for address in addresses:
            cursor.execute(
                'select amount from withdrawal_req where address == ? and completed == 0',
                (address, ))
            req_amounts = [Decimal(str(r[0])) for r in cursor.fetchall()]

            amount = Decimal('0.0')
            for req_amount in req_amounts:
                amount = amount + req_amount

            params[address] = float(amount)

        try:
            txid = coinrpc.call('sendmany', '', params, MINCONF, '',
                                list(addresses))

        except:
            txid = None

        if txid is None:
            cursor.execute(
                'select account, value from withdrawal_req where completed == 0'
            )
            for req in cursor.fetchall():
                account = req[0]
                value = Decimal(str(req[1]))

                cursor.execute(
                    'select balance from account_wallet where account == ?',
                    (account, ))
                balance = Decimal(str(cursor.fetchone()[0]))

                balance = balance + value

                cursor.execute(
                    'update account_wallet set balance = ? where account == ?',
                    (float(balance), account))

            cursor.execute(
                'update withdrawal_req set completed = -1 where completed == 0'
            )
            return

        cursor.execute(
            'update withdrawal_req set completed = 1 where completed == 0')
Ejemplo n.º 3
0
    def check_tx(cursor: sqlite3.Cursor) -> None:
        cursor.execute(
            'select txid from notified_tx where confirmed == 0 and time > ?',
            (int(time.time()) - 60 * MINCONF * 10, ))

        txids = {r[0] for r in cursor.fetchall()}

        if len(txids) == 0:
            return

        for txid in txids:
            result = coinrpc.call('gettransaction', txid)

            if result is None:
                cursor.execute(
                    'update notified_tx set confirmed = -1 where txid == ?',
                    (txid, ))
                continue

            confirmations = result.get('confirmations')

            if confirmations < MINCONF:
                continue

            cursor.execute(
                'select account, value from notified_tx where txid == ?',
                (txid, ))

            for account, value in cursor.fetchall():
                cursor.execute(
                    'select balance from account_wallet where account == ?',
                    (account, ))

                balance = Decimal(str(cursor.fetchone()[0]))
                value = Decimal(str(value))

                balance = balance + value
                cursor.execute(
                    'update account_wallet set balance = ? where account == ?',
                    (float(balance), account))

            cursor.execute(
                'update notified_tx set confirmed = 1 where txid == ?',
                (txid, ))
Ejemplo n.º 4
0
def get_account_address(cursor: sqlite3.Cursor, account: str) -> str:
    cursor.execute('insert or ignore into account_wallet(account) values(?)',
                   (account, ))

    cursor.execute(
        'select address from account_address where account == ? and time > ?',
        (account, int(time.time()) - 60 * 60 * 24 * 7))
    address = cursor.fetchone()

    if address is None:
        address = coinrpc.call('getnewaddress')
        cursor.execute(
            'insert into account_address(account, address, time) values(?, ?, ?)',
            (account, address, int(time.time())))

    else:
        address = address[0]

    return address
Ejemplo n.º 5
0
def execute(text: str, user_id: str, screen_name: str, name: str, from_tweet: bool) -> Optional[str]:
    account = 'twitter-' + user_id
    name = name.split('@')[0] if not name.startswith('@') else name
    command = get_command(text)

    if command['method'] == None:
        return None

    if command['method'] == 'tip':
        if len(command['params']) < 2:
            text = 'tipkotoneの使い方をご確認ください! https://github.com/akarinS/tipkotone/blob/master/README.md'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        if re.match('^@', command['params'][0]):
            to_screen_name = command['params'][0][1:]
            str_amount = command['params'][1]

        elif re.match('^@', command['params'][1]):
            to_screen_name = command['params'][1][1:]
            str_amount = command['params'][0]

        else:
            text = '宛先が間違っています・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        if to_screen_name == screen_name:
            text = '自身には投げ銭できません・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        if to_screen_name == BOTSCREENNAME:
            to_account = 'FREE'

        else:
            to_user = twitter.user(to_screen_name)

            if to_user.get('error') is not None:
                text = '宛先が見つかりませんでした・・・'

                return get_message(text, screen_name) if from_tweet else get_message(text)

            to_user_id = to_user['id_str']
            to_account = 'twitter-' + to_user_id
            to_name = to_user['name']
            to_name = to_name.split('@')[0] if not to_name.startswith('@') else name

        result = aw.move(account, to_account, str_amount)

        if result == 'wrong':
            text = '不正な金額です・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        elif result == 'few':
            text = '金額が小さすぎです・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        elif result == 'insufficient':
            text = '残高が足りません・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        amount = Decimal_to_str(result)

        if to_screen_name == BOTSCREENNAME:
            text = f'{amount}KOTO 寄付していただきありがとうございます!'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        text = f'{name}さんから {to_name}さんへ お心付けです! {amount}KOTO'

        return get_message(text, screen_name, to_screen_name) if from_tweet else get_message(text)

    if command['method'] == 'balance':
        balance, confirming_balance = aw.get_account_balance(account)

        balance = Decimal_to_str(balance)

        if confirming_balance == 0:
            text = f'{name}さんの残高は {balance}KOTO です!'

        else:
            confirming_balance = Decimal_to_str(confirming_balance)
            text = f'{name}さんの残高は {balance}KOTO (+{confirming_balance}KOTO 承認中) です!'

        return get_message(text, screen_name) if from_tweet else get_message(text)

    if command['method'] == 'deposit':
        address = aw.get_account_address(account)

        text = f'{address} に送金してください!'

        return get_message(text, screen_name) if from_tweet else get_message(text)

    if command['method'] == 'withdraw':
        if len(command['params']) < 2:
            text = 'tipkotoneの使い方をご確認ください! https://github.com/akarinS/tipkotone/blob/master/README.md'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        if re.match('^(k|jz)', command['params'][0]):
            address = command['params'][0]
            str_amount = command['params'][1]

        elif re.match('^(k|jz)', command['params'][1]):
            address = command['params'][1]
            str_amount = command['params'][0]

        else:
            text = 'アドレスが間違っています・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        if not coinrpc.call('validateaddress', address)['isvalid']:
            text = 'アドレスが間違っています・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        result = aw.add_withdrawal_request(account, address, str_amount)

        if result == 'wrong':
            text = '不正な金額です・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        elif result == 'few':
            text = '金額が小さすぎです・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        elif result == 'insufficient':
            text = '残高が足りません・・・'

            return get_message(text, screen_name) if from_tweet else get_message(text)

        amount = Decimal_to_str(result)
        text = f'{amount}KOTO の出金リクエストを受け付けました!'

        return get_message(text, screen_name) if from_tweet else get_message(text)

    if command['method'] == 'help':
        text = 'tipkotoneの使い方はこちらです! https://github.com/akarinS/tipkotone/blob/master/README.md'

        return get_message(text, screen_name) if from_tweet else get_message(text)

    if command['method'] == 'follow':
        twitter.follow(user_id)
        text = 'フォローしました!'

        return get_message(text, screen_name) if from_tweet else get_message(text)

    return None