text: # Keypirinha launcher (keypirinha.com)
  
  from datetime import datetime
  import keypirinha as kp
  import keypirinha_util as kpu
  import keypirinha_net as kpnet
  import json
  import urllib
  import os
  import subprocess
  import html
  
  class reddit(kp.Plugin):
      ITEMCAT_RESULT = kp.ItemCategory.USER_BASE + 1
  
      ACTION_OPEN_URL = "open_url"
      ACTION_COPY_URL = "copy_url"
  
      TARGET_POPULAR = "top_popular"
      TARGET_FAVORITE = "favorite"
      TARGET_SEARCH_SUBREDDIT = "search_subreddit"
      TARGET_POPULAR_IN_SUBREDDIT = "popular_in_subreddit"
  
      URL_POPULAR_SUBREDDITS = 'https://www.reddit.com/subreddits/popular.json'
      URL_SEARCH_SUBREDDITS = 'https://www.reddit.com/subreddits/search.json'
      URL_POPULAR_IN = 'https://www.reddit.com/r/{name}/{listing}.json'
  
      DEFAULT_SETTING_FAST_LOAD = False
      USER_SETTING_FAST_LOAD = DEFAULT_SETTING_FAST_LOAD
  
      DEFAULT_SETTING_NSWF = False
      USER_SETTING_NSWF = DEFAULT_SETTING_NSWF
  
      DEFAULT_SETTING_LISTING = "hot"
      USER_SETTING_LISTING = DEFAULT_SETTING_LISTING
      LISTING_SETTINGS = ["hot", "best", "new", "rising"]
  
      last_update = None
  
      def __init__(self):
          super().__init__()
  
      def on_start(self):
          self.logo = 'res://%s/%s'%(self.package_full_name(),'reddit.png')
          self.CACHE = "cache://" + self.package_full_name()
          self.PREVIEW_PATH = self.get_package_cache_path(create=True)
          self.opener = kpnet.build_urllib_opener()
  
          actions = [
              self.create_action(
                  name=self.ACTION_OPEN_URL,
                  label="Read",
                  short_desc="Opens the subreddit in a browser"
              ),
              self.create_action(
                  name=self.ACTION_COPY_URL,
                  label="Copy",
                  short_desc="Copy the URL of subreddit into clipboard"
              )]
          self.set_actions(self.ITEMCAT_RESULT, actions)
          self._popular_suggestions()
          pass
  
      def on_catalog(self):
          catalog = []
          self._load_settings()
          self._popular_suggestions()
          self.set_catalog(catalog)
          catalog.append(self.create_item(
              category=kp.ItemCategory.KEYWORD,
              label="r/Popular",
              short_desc="Show list of popular subreddits",
              target=self.TARGET_POPULAR,
              icon_handle=self.load_icon(self.logo),
              args_hint=kp.ItemArgsHint.REQUIRED,
              hit_hint=kp.ItemHitHint.NOARGS))
  
          counter = 0
          for favorite in self._load_favorites():
              counter += 1
              catalog.append(favorite)
  
          catalog.append(self.create_item(
              category=kp.ItemCategory.KEYWORD,
              label="r/",
              short_desc="Search subreddits",
              target=self.TARGET_SEARCH_SUBREDDIT,
              icon_handle=self.load_icon(self.logo),
              args_hint=kp.ItemArgsHint.REQUIRED,
              hit_hint=kp.ItemHitHint.NOARGS))
  
          self.set_catalog(catalog)
          self.info("Cataloged {} favorites".format(str(counter)))
          pass
  
      def on_suggest(self, user_input, items_chain):
          time_diff = datetime.now() - self.last_update
          if (time_diff.total_seconds() >= 86400):
              self._popular_suggestions()
  
          if not items_chain or items_chain[-1].category() != kp.ItemCategory.KEYWORD:
              return
  
          if self.should_terminate(0.25):
              return
  
          if (items_chain[-1].target() == self.TARGET_POPULAR):
              self.set_suggestions(self.local_popular, kp.Match.ANY, kp.Sort.NONE)
          elif (self.TARGET_FAVORITE in items_chain[-1].target()):
              suggestions = []
              name = items_chain[-1].target()[len(self.TARGET_FAVORITE + "/"):]
              data = self.reddit_request(self.URL_POPULAR_IN.format(name = name, listing = self.USER_SETTING_LISTING), '', 25)
              elements = data['data']['children']
  
              for e in range(len(elements)):
                  cur = elements[e]['data']
                  suggestions.append(self.create_item(
                          category=self.ITEMCAT_RESULT,
                          label=html.unescape(cur['title']),
                          short_desc=html.unescape(cur['selftext']),
                          icon_handle=self.subreddit_icon_by_name(name),
                          target='https://www.reddit.com'+(cur['permalink']),
                          args_hint=kp.ItemArgsHint.FORBIDDEN,
                          hit_hint=kp.ItemHitHint.IGNORE))
              
              self.set_suggestions(suggestions, kp.Match.ANY, kp.Sort.NONE)
          else: #searching for subreddits
              if (len(user_input) == 0):
                  return
  
              suggestions = []
              data = self.reddit_request(self.URL_SEARCH_SUBREDDITS, user_input, 25)
              elements = data['data']['children']
              
              for e in range(len(elements)):
                  cur = elements[e]['data']
                  icon = self.subreddit_icon_or_default(cur, False)
                  suggestions.append(self.create_item(
                      category=self.ITEMCAT_RESULT,
                      label=html.unescape(cur['display_name_prefixed']),
                      short_desc=html.unescape(cur['title']),
                      target='https://www.reddit.com'+(cur['url']),
                      icon_handle=icon,
                      args_hint=kp.ItemArgsHint.FORBIDDEN,
                      hit_hint=kp.ItemHitHint.IGNORE))
                  
              self.set_suggestions(suggestions, kp.Match.ANY, kp.Sort.NONE)
          pass
  
      def on_execute(self, item, action):
          if (action is None or (action is not None and action.name() == self.ACTION_OPEN_URL)):
              kpu.web_browser_command(
                  url = item.target(),
                  execute = True
              )
          else:
              kpu.set_clipboard(item.target())
          pass
  
      def reddit_request(self, url, input, limit):
          request = urllib.request.Request(url)
          if (input is not None and input != ''):
              params = urllib.parse.urlencode({
                  "q": input,
                  "limit": limit,
                  "include_over_18": self.USER_SETTING_NSWF
              })
              request = urllib.request.Request("{}?{}".format(url, params))
  
          request.add_header("User-Agent", "Mozilla/5.0")
          with urllib.request.urlopen(request) as response:
              data = json.loads(response.read())
  
          return data
  
      def subreddit_icon_or_default(self, cur, favorites_list):
          if ((favorites_list or not self.USER_SETTING_FAST_LOAD) and cur['icon_img'] is not None and cur['icon_img'] != ''):
              file_name = "{}.jpg".format(cur['display_name'])
              icon_source = "{}/{}".format(self.CACHE, file_name)
              cache_icon = os.path.join(self.PREVIEW_PATH, file_name)
              if (not os.path.exists(cache_icon)):
                  with self.opener.open(cur['icon_img']) as resp, open(cache_icon, 'w+b') as fp:
                      fp.write(resp.read())
  
              return self.load_icon(icon_source)
  
          return self.load_icon(self.logo)
  
      def subreddit_icon_by_name(self, name):
          file_name = "{}.jpg".format(name)
          icon_source = "{}/{}".format(self.CACHE, file_name)
          cache_icon = os.path.join(self.PREVIEW_PATH, file_name)
          if (not os.path.exists(cache_icon)):
              return self.load_icon(self.logo)
          return self.load_icon(icon_source)
  
      
      def _load_settings(self):
          settings = self.load_settings()
          self.USER_SETTING_FAST_LOAD = settings.get_bool(
              "fast_load", "main",
              self.DEFAULT_SETTING_FAST_LOAD
          )
  
          self.USER_SETTING_NSWF = settings.get_bool(
              "show_nswf", "main",
              self.DEFAULT_SETTING_NSWF
          )
  
          self.USER_SETTING_LISTING = settings.get_enum("listing", "main", fallback=self.DEFAULT_SETTING_LISTING, enum=self.LISTING_SETTINGS).lower()
          if (self.USER_SETTING_LISTING not in self.LISTING_SETTINGS):
              self.USER_SETTING_LISTING = self.DEFAULT_SETTING_LISTING
          pass
  
      def _load_favorites(self):
          items = []
          sections = self.load_settings().sections()
          for config_section in sections:
              if config_section.startswith("#") or not config_section.lower().startswith("r/"):
                  continue
  
              subreddit_name = config_section[len("r/"):]
              data = self.reddit_request(self.URL_SEARCH_SUBREDDITS, subreddit_name, 1)
              cur = data['data']['children'][0]['data']
              icon = self.subreddit_icon_or_default(cur, True)
              items.append(self.create_item(
                  category=kp.ItemCategory.KEYWORD,
                  label="r/{}".format(subreddit_name),
                  short_desc=html.unescape(cur['title']),
                  target=self.TARGET_FAVORITE + "/"+ subreddit_name,
                  icon_handle=icon,
                  args_hint=kp.ItemArgsHint.REQUIRED,
                  hit_hint=kp.ItemHitHint.NOARGS))
          return items
  
      def _popular_suggestions(self):
          suggestions = []
          data = self.reddit_request(self.URL_POPULAR_SUBREDDITS, '', 25)
          elements = data['data']['children']
          for e in range(len(elements)):
              cur = elements[e]['data']
              icon = self.subreddit_icon_or_default(cur, True)
              suggestions.append(self.create_item(
                      category=self.ITEMCAT_RESULT,
                      label=cur['display_name_prefixed'],
                      short_desc=html.unescape(cur['title']),
                      target='https://www.reddit.com'+(cur['url']),
                      icon_handle=icon,
                      args_hint=kp.ItemArgsHint.FORBIDDEN,
                      hit_hint=kp.ItemHitHint.IGNORE))
          self.local_popular = suggestions
          self.last_update = datetime.now()
          pass