#! /usr/bin/env python # pymuseekd - Python tools for museekd # # Copyright (C) 2003-2004 Hyriand # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import messages, driver import sys, time, os from time import sleep max_files = 31 verbose = 1 really_verbose = 0 ban_users = 1 clear_transfers = 1 run_once = 0 states = {} states["Finished"] = 0 states["Transferring"] = 1 states["Negotiating"] = 2 states["Waiting"] = 3 states["Establishing"] = 4 states["Initiating"] = 5 states["Connecting"] = 6 states["Queued"] = 7 states["Address"] = 8 states["Status"] = 9 states["Offline"] = 10 states["ConnectionClosed"] = 11 states["CannotConnect"] = 12 states["Aborted"] = 13 states["Error"] = 14 class MuTransfers(driver.Driver): def __init__(self, trans): driver.Driver.__init__(self) self.trans = trans self.mode = 0 def cb_disconnected(self): if self.mode == 0: self.trans.fatal("disconnected from museekd, bailing out\n") self.mode = 1 try: self.socket.close(); except Exception, e: pass self.socket = None else: pass def cb_login_error(self, error): self.trans.fatal("login error trying to connect to museekd:", error) try: self.socket.close(); except Exception, e: pass self.socket = None def cb_server_state(self, state, username): if not state: self.trans.status("not connected to SoulSeek") else: self.trans.status("connected to SoulSeek, your username:", username) def cb_transfer_state(self, downloads, uploads): self.trans.transfer_state(downloads, uploads) def cb_transfer_update(self, downloads, uploads): self.trans.transfer_update(downloads, uploads) def cb_config_set(self, domain, key, value): pass def cb_transfer_remove(self, transfer): pass class Transfers: def __init__(self, path): path = os.path.expanduser(path) if not os.path.isdir(path): try: os.makedirs(path) except Exception, e: sys.stderr.write("couldn't create log path %s\n" % path) sys.stderr.write(e + "\n") sys.exit(1) self.path = path self.mode = 0 self.trans = None self.uploads_per_user = {} self.upload_count = [] self.past_users = {} self.transfer_list = [] self.last_state = None def write(self, path, message, timestamp = None): if timestamp is None: timestamp = time.time() timestamp = time.strftime("%d %b %Y %H:%M:%S", time.localtime(timestamp)) path = os.path.join(self.path, path) dir = os.path.split(path)[0] if not os.path.isdir(dir): os.makedirs(dir) f = open(path, "a") f.write("%s %s\n" % (timestamp, message)) f.close() def fatal(self, *args): m = " ".join(args) if self.mode == 0: sys.stderr.write(m) self.write("syslog", m) self.mode = 1 os._exit(1) #sys.exit(1) def transfer_state(self, downloads, uploads): if verbose == 1: print "Max Queues per user:", max_files is_upload = 0 for users in uploads: current_transfer = (users[1], users[2], users[3]) username = current_transfer[0] path = current_transfer[1] status = current_transfer[2] path_exists = 0 user_exists = 0 if username in self.uploads_per_user: user_exists = 1 if path in self.uploads_per_user: path_exists = 1 if status in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14): if user_exists == 1: #print "adding transfer to current user" self.uploads_per_user[username] = self.uploads_per_user[username] + 1 self.transfer_list.append(current_transfer) elif user_exists == 0: #print "adding transfer to new user" self.uploads_per_user[username] = 1 self.transfer_list.append(current_transfer) if self.uploads_per_user[username] >= max_files: driver.send(messages.ConfigSet("banned", username, "")) self.uploads_per_user[username] = 0 if clear_transfers == 1: if status in (0, 10, 11, 12, 13, 14): driver.send(messages.TransferRemove(users[0], users[1], users[2])) self.uploads_per_user[username] = self.uploads_per_user[username] - 1 self.transfer_list.remove(current_transfer) if verbose == 1: print "Transfer is Aborted/Errored/Finished so we remove it." print username + ":", self.uploads_per_user[username] #Check for too many files queued for ALL users if ban_users == 1: for users in self.uploads_per_user: if self.uploads_per_user[users] >= max_files: driver.send(messages.ConfigSet("banned", users, "")) if verbose == 1: print "Banned:", users self.uploads_per_user[users] = 0 for user in self.transfer_list[:]: if user[0] == users: self.transfer_list.remove(user) for users in self.uploads_per_user.keys()[:]: if self.uploads_per_user[users] == 0: if verbose == 1: print users, "has 0 active transfers, removing" del self.uploads_per_user[users] if verbose == 1: #print "TRANSFERLIST:", self.transfer_list, "\n" print "USERS:", len(self.uploads_per_user) print len(self.uploads_per_user), "Uploaders ||", len(self.transfer_list), "Uploads" if really_verbose == 1: print "--------------" for x, y in self.uploads_per_user.items(): print y,"\t", x print "--------------" if run_once == 1: sys.exit() #-------------------------------------------------------------------------------------------------- def transfer_update(self, downloads, uploads): # Check if the transfer is already in the list, and if so, remove the old one # and replace it with the new. # Otherwise, just add it. try: sleep(1) except KeyboardInterrupt: sys.exit() is_upload = 0 for users in uploads: current_transfer = (users[1], users[2], users[3]) username = current_transfer[0] path = current_transfer[1] status = current_transfer[2] path_exists = 0 user_exists = 0 if users[0] == 1: is_upload = 1 if verbose == 1: for x, y in states.items(): if y == status: state = x print "Transfer Username:", username, "State:", state, "\nPath:", path if username in self.uploads_per_user: user_exists = 1 #if verbose == 1: #print "USER EXISTS" for paths in self.transfer_list[:]: #print paths if path == paths[1] and username == paths[0]: path_exists = 1 #print "PATH EXISTS" self.transfer_list.remove(paths) # Add transfer to transfer count if status in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14): if user_exists == 1: if verbose == 1: print "adding transfer to current user" self.uploads_per_user[username] = self.uploads_per_user[username] + 1 elif user_exists == 0: if verbose == 1: print "adding transfer to new user" self.uploads_per_user[username] = 1 if user_exists == 1: if verbose == 1: print "Is transfer already queued by user?" if path_exists ==1: self.uploads_per_user[username] = self.uploads_per_user[username] - 1 self.transfer_list.append(current_transfer) if verbose == 1: print "Yes, same transfer" # Remove transfer print username + ":", self.uploads_per_user[username] elif path_exists == 0: self.transfer_list.append(current_transfer) if verbose == 1: print "No, new transfer" # Leave transfer print username + ":", self.uploads_per_user[username] elif user_exists == 0: self.transfer_list.append(current_transfer) if verbose == 1: print "New user:", username # Leave transfer print username + ":", self.uploads_per_user[username] if clear_transfers == 1: if status in (0, 10, 11, 12, 13, 14): driver.send(messages.TransferRemove(users[0], users[1], users[2])) self.uploads_per_user[username] = self.uploads_per_user[username] - 1 self.transfer_list.remove(current_transfer) if verbose == 1: print "Transfer is Aborted/Errored/Finished so we remove it." print username + ":", self.uploads_per_user[username] if is_upload == 1: #Check for too many files queued for ALL users if ban_users == 1: for users in self.uploads_per_user: if self.uploads_per_user[users] >= max_files: driver.send(messages.ConfigSet("banned", users, "")) if verbose == 1: print "Banned:", users self.uploads_per_user[users] = 0 for user in self.transfer_list[:]: if user[0] == users: self.transfer_list.remove(user) #check uploads for users without transfers for users in self.uploads_per_user.keys()[:]: if self.uploads_per_user[users] == 0: if verbose == 1: print users, "has 0 active transfers, removing" del self.uploads_per_user[users] name_not_exist = 1 if verbose == 1: print len(self.uploads_per_user.values()), "Uploaders ||", sum(self.uploads_per_user.values()), "Uploads" if really_verbose == 1: print "--------------" for x, y in self.uploads_per_user.items(): print y,"\t", x print "--------------" def status(self, *args): #self.write("syslog", " ".join(args)) print args[0], args[1] if len(sys.argv) not in (3, 4): print "Syntax: mutransfers.py host:port password [path]" print "or: mutransfers.py /path/to/socket password [path]" sys.exit(-1) (host, password) = sys.argv[1:3] if len(sys.argv) == 4: path = sys.argv[3] else: path = "~/.museekd/logs" trans = Transfers(path) driver = MuTransfers(trans) driver.connect(host, password, messages.EM_TRANSFERS) while 1: driver.process()