Exemplo n.º 1
0
class ChannelSearchGridManager:
    # Code to make this a singleton
    __single = None
   
    def __init__(self,guiUtility):
        if ChannelSearchGridManager.__single:
            raise RuntimeError, "ChannelSearchGridManager is singleton"
        ChannelSearchGridManager.__single = self
        self.guiUtility = guiUtility
        self.guiserver = GUITaskQueue.getInstance()
        
        # Contains all matches for keywords in DB, not filtered by category
        self.hits = {}
        
        self.searchmgr = None
        self.channelcast_db = None
        self.pref_db = None # Nic: for rerankers
        self.mypref_db = None
        self.search_db = None
        
        # For asking for a refresh when remote results came in
        self.gridmgr = None
        
        self.searchkeywords = []
        self.oldsearchkeywords = []
        
        self.category = Category.getInstance()
        
    def getInstance(*args, **kw):
        if ChannelSearchGridManager.__single is None:
            ChannelSearchGridManager(*args, **kw)       
        return ChannelSearchGridManager.__single
    getInstance = staticmethod(getInstance)

    def connect(self):
        session = self.guiUtility.utility.session
        self.torrent_db = session.open_dbhandler(NTFY_TORRENTS)
        self.pref_db = session.open_dbhandler(NTFY_PREFERENCES)
        self.mypref_db = session.open_dbhandler(NTFY_MYPREFERENCES)
        self.search_db = session.open_dbhandler(NTFY_SEARCH)
        self.channelcast_db = session.open_dbhandler(NTFY_CHANNELCAST)
        self.votecastdb = session.open_dbhandler(NTFY_VOTECAST)
        self.searchmgr = SearchManager(self.channelcast_db)
        self.rtorrent_handler = RemoteTorrentHandler.getInstance()
        
    def set_gridmgr(self,gridmgr):
        self.gridmgr = gridmgr

    def getChannelHits(self):
        new_local_hits = self.searchLocalDatabase()

        if DEBUG:
            print >>sys.stderr,'ChannelSearchGridManager: getChannelHits: search found: %d items' % len(self.hits)

        if len(self.hits) == 0:
            return [0, None]
        else:        
            return [len(self.hits),self.hits]

    def getNewChannels(self):
        #all channels with no votes + updated since
        two_months = time() - 5259487
        
        newchannels = self.channelcast_db.getNewChannels(two_months)
        return [len(newchannels), newchannels]

    def getAllChannels(self):
        allchannels = self.channelcast_db.getAllChannels()
        return [len(allchannels), allchannels]
 
    def getSubscriptions(self):
        subscriptions = self.channelcast_db.getMySubscribedChannels()
        return [len(subscriptions), subscriptions]

    def getPopularChannels(self):
        pchannels = self.channelcast_db.getMostPopularChannels()
        return [len(pchannels), pchannels]
    
    def getUpdatedChannels(self):
        lchannels = self.channelcast_db.getLatestUpdated()
        return [len(lchannels), lchannels]
    
    def getMyVote(self, publisher_id):
        return self.votecastdb.getVote(publisher_id, bin2str(self.votecastdb.my_permid))
    
    def getTorrentsFromMyChannel(self):
        return self.getTorrentsFromPublisherId(bin2str(self.votecastdb.my_permid))
    
    def getTorrentFromPublisherId(self, publisher_id, infohash):
        return self.channelcast_db.getTorrentFromPublisherId(publisher_id, infohash)
    
    def getTorrentsFromPublisherId(self, publisher_id, keys = None):
        hits = self.channelcast_db.getTorrentsFromPublisherId(publisher_id, keys)
        self.nrFiltered = 0
        
        enabledcattuples = self.category.getCategoryNames()
        enabledcatslow = ["other"]
        for catname,displayname in enabledcattuples:
            enabledcatslow.append(catname.lower())
        
        def torrentFilter(torrent):
            okCategory = False
            categories = torrent.get("category", ["other"])
            for torcat in categories:
                if torcat.lower() in enabledcatslow:
                    okCategory = True
                    break
                
            if not okCategory:
                self.nrFiltered += 1
            
            okGood = torrent['status'] != 'dead'
            return okGood and okCategory
        
        hits = filter(torrentFilter, hits)
        return  [len(hits), self.nrFiltered, hits]
    
    def getChannel(self, publisher_id):
        return self.channelcast_db.getChannel(publisher_id)
    
    def getChannels(self, publisher_ids):
        return self.channelcast_db.getChannels(publisher_ids)
    
    def spam(self, publisher_id):
        self.votecastdb.spam(publisher_id)
        self.channelcast_db.deleteTorrentsFromPublisherId(publisher_id)
        
    def favorite(self, publisher_id):
        self.votecastdb.subscribe(publisher_id)
    
    def remove_vote(self, publisher_id):
        self.votecastdb.unsubscribe(publisher_id)
        
    def getChannelForTorrent(self, infohash):
        return self.channelcast_db.getMostPopularChannelFromTorrent(infohash)
    
    def getNrTorrentsDownloaded(self, publisher_id):
        return self.channelcast_db.getNrTorrentsDownloaded(publisher_id)
    
    def setSearchKeywords(self, wantkeywords):
        self.searchkeywords = wantkeywords
    
    def searchLocalDatabase(self):
        """ Called by GetChannelHits() to search local DB. Caches previous query result. """
        if self.searchkeywords == self.oldsearchkeywords  and len(self.hits) > 0:
            if DEBUG:
                print >>sys.stderr,"ChannelSearchGridManager: searchLocalDB: returning old hit list", len(self.hits)
            return False
        
        self.oldsearchkeywords = self.searchkeywords
        if DEBUG:
            print >>sys.stderr,"ChannelSearchGridManager: searchLocalDB: Want",self.searchkeywords
         
        if len(self.searchkeywords) == 0 or len(self.searchkeywords) == 1 and self.searchkeywords[0] == '':
            return False

        query = "k "
        for i in self.searchkeywords:
            query = query + i + ' '
        
        #self.hits = self.searchmgr.searchChannels(query)
        hits = self.searchmgr.searchChannels(query)
        
        # Nitin on Feb 5, 2010: temp fix: converting into string format coz most things in GUI use string forms.
        # Fields like permid, infohash, torrenthash are in binary format in each record in 'hits' list.
        votecache = {}
        self.hits = {}
        for hit in hits:
            if bin2str(hit[0]) not in self.hits:
                torrents = {}                 
                torrents[bin2str(hit[2])] = (hit[4], hit[5]) # {infohash:(torrentname, timestamp)}
                if hit[0] not in votecache:
                    votecache[hit[0]] = self.votecastdb.getEffectiveVote(bin2str(hit[0]))

                self.hits[bin2str(hit[0])] = [hit[1], votecache[hit[0]], torrents]
            else:
                torrents = self.hits[bin2str(hit[0])][2]
                if bin2str(hit[2]) not in torrents:
                    torrents[bin2str(hit[2])] = (hit[4], hit[5])
        return True
        
    def gotRemoteHits(self, permid, kws, answers):
        """ Called by GUIUtil when hits come in. """
        self.guiserver.add_task(lambda:self._gotRemoteHits(permid, kws, answers))
        
    def _gotRemoteHits(self, permid, kws, answers):
        #
        # @param permid: the peer who returned the answer to the query
        # @param kws: the keywords of the query that originated the answer
        # @param answers: the filtered answer returned by the peer (publisher_id, publisher_name, infohash, torrenthash, torrentname, timestamp, key

        t1 = time()
        try:
            if DEBUG:
                print >>sys.stderr,"ChannelSearchGridManager: gotRemoteHist: got",len(answers),"for",kws
            
            # Always store the results, only display when in channelsMode
            # We got some replies. First check if they are for the current query
            if self.searchkeywords == kws:
                numResults = 0
                
                for hit in answers.itervalues():
                    #Add to self.hits
                    if hit[0] not in self.hits:
                        self.hits[hit[0]] = [hit[1], self.votecastdb.getEffectiveVote(bin2str(hit[0])), {}]
                    
                    #Extend torrent dict for this channel
                    torrents = self.hits[hit[0]][2]
                    if hit[2] not in torrents:
                        torrents[hit[2]] = (hit[4], hit[5])
                        numResults +=1
                
                if numResults > 0:
                    self.refreshGrid()
                    if DEBUG:
                        print >>sys.stderr,'ChannelSearchGridManager: gotRemoteHits: Refresh grid after new remote channel hits came in', "Took", time() - t1
                return True
            elif DEBUG:
                print >>sys.stderr,"ChannelSearchGridManager: gotRemoteHits: got hits for",kws,"but current search is for",self.searchkeywords
            return False
        except:
            print_exc()
            return False
        
    def refreshGrid(self):
        if self.gridmgr is not None:
            self.gridmgr.refresh_channel()