main.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import os
  2. import logging
  3. import distutils.spawn
  4. from ulauncher.api.client.Extension import Extension
  5. from ulauncher.api.client.EventListener import EventListener
  6. from ulauncher.api.shared.event import KeywordQueryEvent
  7. from ulauncher.api.shared.item.ExtensionResultItem import ExtensionResultItem
  8. from ulauncher.api.shared.item.SmallResultItem import SmallResultItem
  9. from ulauncher.api.shared.action.RenderResultListAction import RenderResultListAction
  10. from ulauncher.api.shared.action.RunScriptAction import RunScriptAction
  11. logging.basicConfig()
  12. logger = logging.getLogger(__name__)
  13. # Initialize items cache and Remmina profiles path
  14. remmina_bin = ''
  15. # Locate Remmina profiles and binary
  16. remmina_profiles_path = "{}/.local/share/remmina".format(os.environ.get('HOME'))
  17. remmina_bin = distutils.spawn.find_executable('remmina')
  18. # This extension is useless without remmina
  19. if remmina_bin is None or remmina_bin == '':
  20. logger.error('Remmina executable path could not be determined')
  21. exit()
  22. # Check if Remmina profiles directory exists
  23. if not os.path.isdir(remmina_profiles_path):
  24. logger.error("Remmina profiles directory doesn't exist ({})".format(remmina_profiles_path))
  25. exit()
  26. class RemminaExtension(Extension):
  27. def __init__(self):
  28. super(RemminaExtension, self).__init__()
  29. self.subscribe(KeywordQueryEvent, KeywordQueryEventListener())
  30. def list_profiles(self, query):
  31. profiles = []
  32. items_cache = []
  33. try:
  34. # Get list of profile files from Remmina directory
  35. for profile in os.listdir(remmina_profiles_path):
  36. if profile.endswith(".remmina"):
  37. profiles.append(os.path.join(remmina_profiles_path, profile))
  38. # Get sorted list of profiles
  39. temp = profiles
  40. profiles = sorted(temp)
  41. except Exception as e:
  42. print('Failed getting profile files')
  43. for p in profiles:
  44. base = os.path.basename(p)
  45. title = os.path.splitext(base)[0]
  46. desc, proto = profile_details(p)
  47. # Search for query inside filename and profile description
  48. # Multiple strings can be used to search in description
  49. # all() is used to achieve a AND search (include all keywords)
  50. keywords = query.split(" ")
  51. # if (query in base.lower()) or (query in desc.lower()):
  52. if (query in base.lower()) or all(x in desc for x in keywords):
  53. items_cache.append(create_item(title, proto, p, desc, p))
  54. return items_cache
  55. class KeywordQueryEventListener(EventListener):
  56. def on_event(self, event, extension):
  57. # Get query
  58. term = (event.get_argument() or '').lower()
  59. # Display all items when query empty
  60. profiles_list = extension.list_profiles(term)
  61. return RenderResultListAction(profiles_list)
  62. def create_item(name, icon, keyword, description, on_enter):
  63. return ExtensionResultItem(
  64. name=name,
  65. description=description,
  66. icon='images/{}.svg'.format(icon),
  67. on_enter=RunScriptAction('#!/usr/bin/env bash\n{} -c {}\n'.format(remmina_bin, on_enter), None)
  68. )
  69. def profile_details(profile_path):
  70. if os.path.isfile(profile_path):
  71. with open(profile_path, "r") as f:
  72. # Read profile file lines
  73. lines = f.read().split("\n")
  74. # Initialize strings
  75. desc = name = username = group = proto = ""
  76. # Parse lines for relevant details
  77. for line in lines:
  78. # Profile name
  79. if line.startswith("name="):
  80. elem = line.split("name=")
  81. if len(elem[1]) > 0:
  82. name = elem[1]
  83. # Profile username (optional)
  84. if "username=" in line:
  85. elem = line.split("username=")
  86. # if len(elem) > 1:
  87. if len(elem[0]) == 0 and len(elem[1]) > 0:
  88. username = elem[1]
  89. elif len(elem[0]) > 0 and len(elem[1]) > 0:
  90. username = elem[1]
  91. # Profile server and port
  92. if line.startswith("server="):
  93. elem = line.split("server=")
  94. if len(elem[1]) > 0:
  95. server = elem[1]
  96. # Profile group name
  97. if line.startswith("group="):
  98. elem = line.split("group=")
  99. if len(elem[1]) > 0:
  100. group = elem[1]
  101. # Profile protocol (for different icons)
  102. if line.startswith("protocol="):
  103. elem = line.split("protocol=")
  104. if len(elem[1]) > 0:
  105. proto = elem[1].strip().lower()
  106. else:
  107. pass
  108. if len(username) > 0:
  109. server = "{username}@{server}".format(username=username,
  110. server=server)
  111. if len(proto) > 0:
  112. server = "{proto}://{server}".format(proto=proto,
  113. server=server)
  114. if len(group) > 0:
  115. group = " | {group}".format(group=group)
  116. desc = "{name} | {server} {group}".format(name=name,
  117. server=server,
  118. group=group)
  119. return desc, proto
  120. else:
  121. # Default values
  122. return "", "rdp"
  123. if __name__ == '__main__':
  124. RemminaExtension().run()