Beispiel #1
0
 def remove(self, sender, arguments):
     """
 user: root
 remove address|name1|hashtag2
 will loop over all addresses and remove those that match params
 """
     if self.is_root(sender):
         try:
             rows = utils.search_db(
                 self.conn,
                 'SELECT address, names, hashtags FROM btcaddresses')
             rmcount = 0
             for row in rows:
                 if arguments == row[0] or arguments.lower(
                 ) in row[1].lower() or arguments.lower() in row[2].lower():
                     query = 'DELETE FROM btcaddresses WHERE address="%s"' % (
                         row[0])
                     utils.populate_db(self.conn, query)
                     rmcount += 1
             if rmcount:
                 return "deleted %d rows matching pattern: %s" % (rmcount,
                                                                  arguments)
             else:
                 self.error = "could not find any rows matching pattern: %s" % (
                     arguments)
                 return None
         except:
             import traceback
             traceback.print_exc()
             self.error = "incorrect params for this command: remove %s" % (
                 arguments)
             return None
     else:
         self.error = "user %s is not authorized" % (sender)
         return None
Beispiel #2
0
 def add(self, sender, arguments):
     """
 user: root
 add address name1|name2 #hashtag1|#hashtag2 good|bad|unknown
 will add new entry and enable tracking|tweeting|txstats by default
 """
     if self.is_root(sender):
         try:
             address, names, hashtags, status = arguments.split()
             rows = utils.search_db(
                 self.conn,
                 'SELECT address, names, hashtags FROM btcaddresses WHERE address="%s"'
                 % (address))
             if rows and len(rows):
                 self.error = "address %s already in database" % (address)
                 return None
             else:
                 query = 'INSERT INTO btcaddresses (address, names, hashtags, status) VALUES ("%s", "%s", "%s", %d)' % (
                     address, names, hashtags,
                     self.config["statuses"][status.lower()]
                     if status.lower() in self.config["statuses"] else 0)
                 utils.populate_db(self.conn, query)
                 return "added %s to database (%s, %s, %s)" % (
                     address, names, hashtags, status.lower())
         except:
             self.error = "incorrect params for this command"
             return None
     else:
         self.error = "user %s is not authorized" % (sender)
         return None
Beispiel #3
0
 def update_balance(self, address):
     balance = utils.btc_balance(address)
     balance /= self.config["satoshi2btc"]
     if balance >= 0:
         query = 'UPDATE btcaddresses SET balance=%f WHERE address="%s"' % (
             balance, address)
         utils.populate_db(self.conn, query)
         return True
     return False
Beispiel #4
0
 def update(self):
     rows = utils.search_db(
         self.conn, 'SELECT txhash, timestamp_human FROM btctransactions')
     if rows and len(rows):
         for row in rows:
             txhash, timestamp_human = row[0], row[1]
             if timestamp_human:
                 query = 'UPDATE btctransactions SET timestamp_human="%s" WHERE txhash="%s"' % (
                     timestamp_human.replace("(UTC)", "UTC"), txhash)
                 utils.populate_db(self.conn, query)
Beispiel #5
0
    def run(self):
        # load config from database
        self.load_config()

        utils.info("starting statscollector module")
        while True:
            # update exchange rates
            rates = utils.get_exchange_rates()
            if rates and len(rates):
                insertquery = 'INSERT INTO forex (btc2usd, btc2eur, btc2gbp, btc2cad, btc2sgd, btc2jpy, btc2inr) VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s")' % (
                    rates["USD"],
                    rates["EUR"],
                    rates["GBP"],
                    rates["CAD"],
                    rates["SGD"],
                    rates["JPY"],
                    rates["INR"],
                )
            deletequery = 'DELETE FROM forex WHERE fid IN (SELECT fid FROM forex LIMIT 1)'
            # add latest values
            utils.populate_db(self.conn, insertquery)
            # delete first row
            utils.populate_db(self.conn, deletequery)
            utils.info("updated forex rates")
            # update btc address balance
            rows = utils.search_db(self.conn,
                                   'SELECT address FROM btcaddresses')
            if rows and len(rows):
                count = 0
                for entry in rows:
                    if self.update_balance(entry[0]):
                        count += 1
                utils.info("updated balance for %d tracked addresses" %
                           (count))

            # load exchange rates from stats table
            query = 'SELECT btc2usd FROM forex ORDER BY fid DESC LIMIT 1'
            rows = utils.search_db(self.conn, query)
            self.config["exchangerates"]["btc2usd"] = rows[0][0]

            # summary of all addresses
            summary = self.address_summary()

            # lowest|highest balance for ransom/donation recipients
            # most common sender/receiver
            # most common sender/receiver for ransom/donation
            # lowest|highest paying|receiving sender/receiver
            # highest balance/txs/rcvd/sent

            ## sleep
            time.sleep(self.config["statscollectiondelay"])

            # reload config from database
            self.load_config()
Beispiel #6
0
 def auth(self, sender, arguments):
     """
 user: root
 auth add|remove handle
 will add|remove handle in authorized users list
 """
     if self.is_root(sender):
         try:
             cmd, handle = arguments.split()
             if cmd.lower() in ["add", "remove"]:
                 if cmd.lower() == "add":
                     rows = utils.search_db(
                         self.conn, 'SELECT authorizedusers FROM config')
                     authusers = rows[0][0]
                     if handle not in authusers:
                         authusers = authusers.split("|")
                         authusers.append(handle)
                         query = 'UPDATE config SET authorizedusers="%s"' % (
                             "|".join(authusers))
                         utils.populate_db(self.conn, query)
                         return "user %s is authorized now" % (handle)
                     else:
                         self.error = "user %s already authorized" % (
                             handle)
                         return None
                 else:
                     rows = utils.search_db(
                         self.conn, 'SELECT authorizedusers FROM config')
                     authusers = rows[0][0]
                     if handle in authusers:
                         authusers = authusers.split("|")
                         authusers.remove(handle)
                         query = 'UPDATE config SET authorizedusers="%s"' % (
                             "|".join(authusers))
                         utils.populate_db(self.conn, query)
                         return "user %s is not authorized now" % (handle)
                     else:
                         self.error = "user %s is not authorized" % (handle)
                         return None
             else:
                 self.error = "incorrect subcommand for this command: auth %s" % (
                     arguments)
         except:
             import traceback
             traceback.print_exc()
             self.error = "incorrect params for this command: auth %s" % (
                 arguments)
             return None
     else:
         self.error = "user %s is not authorized" % (sender)
         return None
Beispiel #7
0
 def txstats(self, sender, arguments):
     """
 user: root
 txstats start|stop address|name1|hashtag2
 will loop over all addresses and enable|disable stats tweet for those that match params
 """
     if self.is_root(sender):
         try:
             cmd, pattern = arguments.split()
             if cmd.lower() in ["start", "stop"]:
                 rows = utils.search_db(
                     self.conn,
                     'SELECT address, names, hashtags FROM btcaddresses')
                 trkcount = 0
                 for row in rows:
                     if pattern == row[0] or pattern.lower(
                     ) in row[1].lower() or pattern.lower() in row[2].lower(
                     ):
                         if cmd.lower() == "start":
                             query = 'UPDATE btcaddresses SET dostats=1 WHERE address="%s"' % (
                                 row[0])
                             utils.populate_db(self.conn, query)
                             trkcount += 1
                         else:
                             query = 'UPDATE btcaddresses SET dostats=0 WHERE address="%s"' % (
                                 row[0])
                             utils.populate_db(self.conn, query)
                             trkcount += 1
                 if trkcount:
                     return "updated %d rows matching pattern: %s" % (
                         trkcount, pattern)
                 else:
                     self.error = "could not find any rows matching pattern: %s" % (
                         pattern)
                     return None
             else:
                 self.error = "incorrect subcommand for this command: txstats %s" % (
                     arguments)
         except:
             import traceback
             traceback.print_exc()
             self.error = "incorrect params for this command: txstats %s" % (
                 arguments)
             return None
     else:
         self.error = "user %s is not authorized" % (sender)
         return None
Beispiel #8
0
 def update(self, sender, arguments):
     """
 user: root
 update address|name1|hashtag2 good|bad|unknown
 will loop over all addresses and update status for those that match params
 """
     if self.is_root(sender):
         try:
             pattern, status = arguments.split()
             if status.lower() in self.config["statuses"]:
                 rows = utils.search_db(
                     self.conn,
                     'SELECT address, names, hashtags FROM btcaddresses')
                 upcount = 0
                 for row in rows:
                     if pattern == row[0] or pattern.lower(
                     ) in row[1].lower() or pattern.lower() in row[2].lower(
                     ):
                         query = 'UPDATE btcaddresses SET status=%d WHERE address="%s"' % (
                             self.config["statuses"][status.lower()],
                             row[0])
                         utils.populate_db(self.conn, query)
                         upcount += 1
                 if upcount:
                     return "updated %d rows matching pattern: %s" % (
                         upcount, pattern)
                 else:
                     self.error = "could not find any rows matching pattern: %s" % (
                         pattern)
                     return None
             else:
                 self.error = "incorrect status: %s" % (status)
                 return None
         except:
             import traceback
             traceback.print_exc()
             self.error = "incorrect params for this command: update %s" % (
                 arguments)
             return None
     else:
         self.error = "user %s is not authorized" % (sender)
         return None
Beispiel #9
0
Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    username = Column(String)
    password = Column(String)

    def __repr__(self):
        return "<User(username='******', password='******')>" % (self.username,
                                                         self.password)


# create the schema
Base.metadata.create_all(engine)

# prepare a db session
session_factory = sessionmaker(bind=engine)
#                                autoflush=True,
#                                autocommit=False,
#                                )
DBSession = scoped_session(session_factory)

if __name__ == '__main__':
    from utils import populate_db

    # insert birdie_settings.MAX_USERS users into the db
    populate_db()
Beispiel #10
0
def populate():
    from utils import populate_db
    populate_db()
Beispiel #11
0
# -*- coding: utf-8 -*-
from wsgiref.simple_server import make_server
from wsgiref.validate import validator
from wsgiref.util import application_uri, request_uri
from urls import urls
from views import view_404
from utils import populate_db
from settigs import DB_NAME


def app(environ, start_response):
    uri = request_uri(environ,
                      include_query=False).replace(application_uri(environ),
                                                   '')
    yield urls.get(uri, view_404)(environ, start_response).encode('utf-8')


if __name__ == '__main__':
    populate_db(DB_NAME)
    with make_server('', 8080, validator(app)) as server:
        server.serve_forever()
Beispiel #12
0
Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    username = Column(String)
    password = Column(String)

    def __repr__(self):
        return "<User(username='******', password='******')>" % (
                self.username, self.password)


# create the schema                
Base.metadata.create_all(engine)    

# prepare a db session
session_factory = sessionmaker(bind=engine)
#                                autoflush=True,
#                                autocommit=False,
#                                )
DBSession = scoped_session(session_factory)


if __name__ == '__main__':
    from utils import populate_db
    
    # insert birdie_settings.MAX_USERS users into the db
    populate_db()
Beispiel #13
0
    def update_database(self, rows):
        for row in rows:
            # get blockchain.info tags for current address
            tags = self.get_tags(row[0])

            # get list of all txs for current address
            txs = self.get_txs(row[0])
            if txs:
                if tags and len(tags):
                    rcvd = txs["total_received"] / self.config["satoshi2btc"]
                    sent = txs["total_sent"] / self.config["satoshi2btc"]
                    balance = txs["final_balance"] / self.config["satoshi2btc"]
                    query = 'UPDATE btcaddresses SET tags="%s", txs=%d, rcvd=%f, sent=%f, balance=%f WHERE address="%s"' % (
                        "|".join(tags), txs["n_tx"], rcvd, sent, balance,
                        row[0])
                else:
                    rcvd = txs["total_received"] / self.config["satoshi2btc"]
                    sent = txs["total_sent"] / self.config["satoshi2btc"]
                    balance = txs["final_balance"] / self.config["satoshi2btc"]
                    query = 'UPDATE btcaddresses SET txs=%d, rcvd=%f, sent=%f, balance=%f WHERE address="%s"' % (
                        txs["n_tx"], rcvd, sent, balance, row[0])
                utils.populate_db(self.conn, query)
                txcount = 0
                for tx in txs["txs"]:
                    # dict to store tx information
                    txinfo = {
                        "source": {},
                        "destination": {},
                        "txhash": tx["hash"],
                        "timestamp_epoch": tx["time"],
                        "timestamp_human":
                        utils.epoch_to_human_utc(tx["time"]),
                        "relayip": tx["relayed_by"],
                        "rcvd": 0,
                        "sent": 0,
                    }

                    # check if this tx is already in db
                    if utils.search_db(
                            self.conn,
                            'SELECT txhash FROM btctransactions WHERE txhash="%s"'
                            % (tx["hash"])):
                        continue

                    # load source addresses and btc values
                    for entry in tx["inputs"]:
                        if entry.get("prev_out",
                                     None) and entry["prev_out"].get(
                                         "addr", None
                                     ) is not None and entry["prev_out"].get(
                                         "addr", None) not in txinfo["source"]:
                            txinfo["source"][
                                entry["prev_out"]["addr"]] = entry["prev_out"][
                                    "value"] / self.config["satoshi2btc"]
                            if utils.search_db(
                                    self.conn,
                                    'SELECT address FROM btcaddresses WHERE address="%s"'
                                    % (entry["prev_out"]["addr"])):
                                txinfo["sent"] = 1

                    # load destination addresses and btc values
                    for entry in tx["out"]:
                        if entry.get("addr", None) is not None and entry[
                                "addr"] not in txinfo["destination"]:
                            txinfo["destination"][entry["addr"]] = entry[
                                "value"] / self.config["satoshi2btc"]
                            if utils.search_db(
                                    self.conn,
                                    'SELECT address FROM btcaddresses WHERE address="%s"'
                                    % (entry["addr"])):
                                txinfo["rcvd"] = 1

                    # a tx with sent and rcvd both set has to be ignored, for now
                    if txinfo["sent"] == 1 and txinfo["rcvd"] == 1:
                        continue

                    # update btcaddresses table with in|out address information
                    alladdresses = utils.all_dict_keys(
                        [txinfo["source"], txinfo["destination"]])
                    for address in alladdresses:
                        query = 'SELECT inaddresses, outaddresses FROM btcaddresses WHERE address="%s"' % (
                            address)
                        rows = utils.search_db(self.conn, query)
                        if rows and len(rows) and rows[0] and len(rows[0]):
                            if rows[0][0]:
                                inaddrs = "|".join(
                                    list(
                                        set(
                                            list(txinfo["source"].keys()) +
                                            [rows[0][0]])))
                            else:
                                inaddrs = "|".join(
                                    list(set(txinfo["source"].keys())))
                            if rows[0][1]:
                                outaddrs = "|".join(
                                    list(
                                        set(
                                            list(txinfo["destination"].keys())
                                            + [rows[0][1]])))
                            else:
                                outaddrs = "|".join(
                                    list(set(txinfo["destination"].keys())))
                                query = 'UPDATE btcaddresses SET inaddresses="%s", outaddresses="%s", lasttx_epoch="%s", lasttx_human="%s" WHERE address="%s"' % (
                                    inaddrs, outaddrs,
                                    txinfo["timestamp_epoch"],
                                    txinfo["timestamp_human"], address)
                            utils.populate_db(self.conn, query)

                    # update btctransactions table
                    amountbtc, address = 0, None
                    senders = list(txinfo["source"].keys())
                    for addr in txinfo["source"].keys():
                        if utils.search_db(
                                self.conn,
                                'SELECT address FROM btcaddresses WHERE address="%s"'
                                % (addr)):
                            address = addr
                            amountbtc = txinfo["source"][addr]
                            break
                    receivers = list(txinfo["destination"].keys())
                    for addr in txinfo["destination"].keys():
                        if utils.search_db(
                                self.conn,
                                'SELECT address FROM btcaddresses WHERE address="%s"'
                                % (addr)):
                            address = addr
                            amountbtc = txinfo["destination"][addr]
                            break

                    query = 'INSERT INTO btctransactions (txhash, address, timestamp_epoch, timestamp_human, amountbtc, relayip, rcvd, sent, receivers, senders) VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")' % (
                        txinfo["txhash"],
                        address if address else "",
                        txinfo["timestamp_epoch"],
                        txinfo["timestamp_human"],
                        amountbtc,
                        txinfo["relayip"],
                        txinfo["rcvd"],
                        txinfo["sent"],
                        "|".join(receivers)
                        if receivers and len(receivers) else "",
                        "|".join(senders) if senders and len(senders) else "",
                    )
                    utils.populate_db(self.conn, query)
                    txcount += 1

                if txcount:
                    utils.info("added %d new transactions for %s" %
                               (txcount, row[2]))
Beispiel #14
0
  def parser(self, message):
    # load exchange rates from stats table
    query = 'SELECT btc2usd FROM forex ORDER BY fid DESC LIMIT 1'
    rows = utils.search_db(self.conn, query)
    self.config["exchangerates"]["btc2usd"] = rows[0][0]

    # dict to store tx information
    txinfo = {
      "source": {},
      "destination": {},
      "txhash": message["x"]["hash"],
      "timestamp_epoch": message["x"]["time"],
      "timestamp_human": utils.epoch_to_human_utc(message["x"]["time"]),
      "relayip": message["x"]["relayed_by"],
      "rcvd": 0,
      "sent": 0,
    }

    # load source addresses and btc values
    for entry in message["x"]["inputs"]:
      if entry["prev_out"]["addr"] is not None and entry["prev_out"]["addr"] not in txinfo["source"]:
        txinfo["source"][entry["prev_out"]["addr"]] = entry["prev_out"]["value"]/self.config["satoshi2btc"]
        if utils.search_db(self.conn, 'SELECT address FROM btcaddresses WHERE address="%s"' % (entry["prev_out"]["addr"])):
          txinfo["sent"] = 1

    # load destination addresses and btc values
    for entry in message["x"]["out"]:
      if entry["addr"] is not None and entry["addr"] not in txinfo["destination"]:
        txinfo["destination"][entry["addr"]] = entry["value"]/self.config["satoshi2btc"]
        if utils.search_db(self.conn, 'SELECT address FROM btcaddresses WHERE address="%s"' % (entry["addr"])):
          txinfo["rcvd"] = 1

    # a tx with sent and rcvd both set has to be ignored, for now
    if txinfo["sent"] == 1 and txinfo["rcvd"] == 1:
      utils.info("ignored txhash https://blockchain.info/tx/%s" % (txinfo["txhash"]))
      return

    # update btcaddresses table with in|out address information
    alladdresses = utils.all_dict_keys([txinfo["source"], txinfo["destination"]])
    for address in alladdresses:
      query = 'SELECT inaddresses, outaddresses FROM btcaddresses WHERE address="%s"' % (address)
      rows = utils.search_db(self.conn, query)
      if rows and len(rows) and rows[0] and len(rows[0]):
        if rows[0][0]:
          inaddrs = "|".join(list(set(list(txinfo["source"].keys()) + [rows[0][0]])))
        else:
          inaddrs = "|".join(list(set(txinfo["source"].keys())))
        if rows[0][1]:
          outaddrs = "|".join(list(set(list(txinfo["destination"].keys()) + [rows[0][1]])))
        else:
          outaddrs = "|".join(list(set(txinfo["destination"].keys())))
        query = 'UPDATE btcaddresses SET inaddresses="%s", outaddresses="%s", lasttx_epoch="%s", lasttx_human="%s" WHERE address="%s"' % (inaddrs, outaddrs, txinfo["timestamp_epoch"], txinfo["timestamp_human"], address)
        utils.populate_db(self.conn, query)

    # update btctransactions table
    amountbtc, address, senders = 0, None, []
    senders = list(txinfo["source"].keys())
    for addr in txinfo["source"].keys():
      if utils.search_db(self.conn, 'SELECT address FROM btcaddresses WHERE address="%s"' % (addr)):
        address = addr
        amountbtc = txinfo["source"][addr]
        break
    receivers = list(txinfo["destination"].keys())
    for addr in txinfo["destination"].keys():
      if utils.search_db(self.conn, 'SELECT address FROM btcaddresses WHERE address="%s"' % (addr)):
        address = addr
        amountbtc = txinfo["destination"][addr]
        break
    query = 'INSERT INTO btctransactions (txhash, address, timestamp_epoch, timestamp_human, amountbtc, relayip, rcvd, sent, receivers, senders) VALUES ("%s", "%s", %d, "%s", "%s", "%s", "%s", "%s", "%s", "%s")' % (
      txinfo["txhash"],
      address if address else "",
      txinfo["timestamp_epoch"],
      txinfo["timestamp_human"],
      amountbtc,
      txinfo["relayip"],
      txinfo["rcvd"],
      txinfo["sent"],
      "|".join(receivers) if receivers and len(receivers) else "",
      "|".join(senders) if senders and len(senders) else "",
    )
    utils.populate_db(self.conn, query)
    utils.info("added transaction rows to localdb (sent: %s, rcvd: %s)" % (True if txinfo["sent"] else False, True if txinfo["rcvd"] else False))

    # add tweet message to tw queue
    tweet = []
    for address in txinfo["source"].keys():
      rows = utils.search_db(self.conn, 'SELECT names, balance, hashtags, status FROM btcaddresses WHERE address="%s" AND dotweet=1' % (address))
      if rows and len(rows) and rows[0] and len(rows[0]):
        names, balance, hashtags, status = rows[0][0], rows[0][1], rows[0][2], rows[0][3]
        self.update_balance(address)
        balance = balance*self.config["exchangerates"]["btc2usd"] if balance >= 0 else -1
        for tag in self.config["ignorehashtags"].split("|"):
          hashtags = hashtags.replace(tag, "")
        hashtags = hashtags.strip("|")
        sender = None
        if hashtags and hashtags != "":
          sender = hashtags
        elif names and names != "":
          sender = "https://blockchain.info/address/%s (%s)" % (address, names)
        else:
          sender = "https://blockchain.info/address/%s" % (address)
        if status == 0:
          emoji = random.choice(self.config["neutralemojis"].split("|"))
        elif status == 1:
          emoji = random.choice(self.config["happyemojis"].split("|"))
        elif status == 2:
          emoji = random.choice(self.config["sademojis"].split("|"))
        else:
          emoji = random.choice(self.config["neutralemojis"])
        tweet.append("%s sent %f BTC ($%.2f) (https://blockchain.info/tx/%s) %s %s" % (
          sender,
          txinfo["source"][address],
          txinfo["source"][address]*self.config["exchangerates"]["btc2usd"],
          txinfo["txhash"],
          #"(balance: %.02f) " % balance if balance >= 0 else "",
          self.config["generichashtags"],
          emoji))
    for address in txinfo["destination"].keys():
      rows = utils.search_db(self.conn, 'SELECT names, balance, hashtags, status FROM btcaddresses WHERE address="%s" AND dotweet=1' % (address))
      if rows and len(rows) and rows[0] and len(rows[0]):
        names, balance, hashtags, status = rows[0][0], rows[0][1], rows[0][2], rows[0][3]
        self.update_balance(address)
        balance = balance*self.config["exchangerates"]["btc2usd"] if balance >= 0 else -1
        for tag in self.config["ignorehashtags"].split("|"):
          hashtags = hashtags.replace(tag, "")
        hashtags = hashtags.strip("|")
        receiver = None
        if hashtags and hashtags != "":
          receiver = hashtags
        elif names and names != "":
          receiver = "https://blockchain.info/address/%s (%s)" % (address, names)
        else:
          receiver = "https://blockchain.info/address/%s" % (address)
        if status == 0:
          emoji = random.choice(self.config["neutralemojis"].split("|"))
        elif status == 1:
          emoji = random.choice(self.config["happyemojis"].split("|"))
        elif status == 2:
          emoji = random.choice(self.config["sademojis"].split("|"))
        else:
          emoji = random.choice(self.config["neutralemojis"])
        tweet.append("%s rcvd %f BTC ($%.2f) (https://blockchain.info/tx/%s) %s %s" % (
          receiver,
          txinfo["destination"][address],
          txinfo["destination"][address]*self.config["exchangerates"]["btc2usd"],
          txinfo["txhash"],
          #"(balance: %.02f) " % balance if balance >= 0 else "",
          self.config["generichashtags"],
          emoji))
    if tweet and len(tweet):
      tweet = " ".join(tweet)
      tweet = utils.unicodecp_to_unicodestr(tweet)
      utils.enqueue(queuefile=self.config["tweetqueue"], data=tweet)
      utils.info("%s" % (tweet))
      utils.info("added message to queue: %s (%d total)" % (self.config["tweetqueue"], utils.queuecount(queuefile=self.config["tweetqueue"])))