Skip to content

Building a search function

Masta2002 edited this page Oct 4, 2026 · 2 revisions

Moving through menus with the arrow keys of a remote is slow, so the fastest way to a movie is the search. E2iPlayer brings everything around it - the keyboard, search suggestions, the search history and its editor. The host only has to turn the typed words into a result list.

The example is the search of 🔗hostTemplate.py.

1. Find out how the site searches

Search for something in a desktop browser and look at the url (or, with the developer tools, at the request in the Network tab). Most sites use a GET url like

https://www.mysite.com/?s=the+general
https://www.mysite.com/page/2/?s=the+general     (page 2)

Some send a form with POST, some ask a JSON API (/api/search?q=...) while the page is typed into.

2. The menu entries

self.MENU = [
    {'category': 'list_items', 'title': _('Movies'), 'url_tpl': self.getFullUrl('/movies/page/{page}/')},
    ...
] + self.searchItems()

searchItems() adds four entries: Search (category search, opens the keyboard), Search history (search_history), Edit search history and Delete search history (both handled by E2iPlayer itself). It needs a history file, which is set by the history parameter in __init__:

CBaseHostClass.__init__(self, {'history': 'mysite', 'cookie': 'mysite.cookie'})

and the True in CHostBase.__init__(self, MySite(), True, []) of the IPTVHost class.

3. Routing in handleService

elif category in ('search', 'search_next_page'):
    cItem = dict(self.currItem)
    cItem.update({'search_item': False, 'name': 'category'})
    self.listSearchResult(cItem, searchPattern, searchType)
elif category == 'search_history':
    self.listsHistory({'name': 'history', 'category': 'search'}, 'desc')

searchPattern is what the user typed (or picked from the history). The history entries are rows with category search, so picking one runs the same search again.

4. The result list

from Plugins.Extensions.IPTVPlayer.p2p3.UrlLib import urllib_quote_plus

def listSearchResult(self, cItem, searchPattern, searchType):
    printDBG('MySite.listSearchResult [%s]' % searchPattern)
    # the result list is an ordinary list_items list, so paging works the same way
    self.listItems({'name': 'category', 'category': 'list_items',
                    'url_tpl': self.getFullUrl('/page/{page}/?s=') + urllib_quote_plus(searchPattern)})
  • urllib_quote_plus turns spaces into + and encodes special characters. Import it from p2p3.UrlLib - urllib.quote_plus exists only on Python 2, urllib.parse.quote_plus only on Python 3. Use urllib_quote when the site wants %20.
  • When the results look like a normal list of the site, reuse the list function - then the search gets the same rows, paging, watched flag and favourites for free.

A search with POST passes the form fields as a dict:

sts, data = self.getPage(self.getFullUrl('/search'), dict(self.defaultParams), {'query': searchPattern, 'type': 'all'})

A JSON API is read with json_loads (libs/e2ijson.py) instead of the HTML helpers:

sts, data = self.getPage(self.getFullUrl('/api/search?q=') + urllib_quote_plus(searchPattern))
if not sts:
    return
try:
    results = json_loads(data).get('results', [])
except Exception:
    printExc()
    return
for entry in results:
    ...

5. Search types (optional)

When the site can search movies and series separately, offer the choice in the keyboard - in the IPTVHost class:

class IPTVHost(GenericFolderWatchedHostMixin, CHostBase):
    ...
    def getSearchTypes(self):
        return [(_('Movies'), 'movies'), (_('Series'), 'series')]

The second value of the chosen entry arrives as searchType in listSearchResult(), and is stored in the search history with the words.

6. Search suggestions

While the user types, the keyboard can show suggestions. Without any code, hosts in the group moviesandseries of hostgroups.txt get IMDb suggestions (Filmweb when they are also in polish), all others Google - the user can change this in the settings. A host that knows better returns its own provider from the IPTVHost class (providers are in IPTVPlayer/suggestions/):

def getSuggestionsProvider(self, index=-1):
    from Plugins.Extensions.IPTVPlayer.suggestions.google import SuggestionsProvider as google_Provider
    return RetHost(status=RetHost.OK, value=[google_Provider()])

7. Test

  • a word with several results, one with none (the list should be empty, not an error), words with spaces and umlauts/accents
  • "Next page" of the results, if the site pages them
  • picking an entry from the search history, editing and deleting the history

Based on the original text by Maxbambi, thank you!

Clone this wiki locally