A Python terminal app for NotePost.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
4.8KB

  1. #!/usr/bin/env python3
  2. # This Source Code Form is subject to the terms of the Mozilla Public
  3. # License, v. 2.0. If a copy of the MPL was not distributed with this
  4. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  5. import sys
  6. import os
  7. try:
  8. sys.path.append(os.path.dirname(os.path.realpath(__file__)))
  9. except:
  10. pass
  11. import tempfile
  12. import i18n
  13. import validators
  14. import requests
  15. import api
  16. from config import *
  17. from termcolors import *
  18. from getpass import getpass
  19. editor = "/usr/bin/editor"
  20. notes = {}
  21. def firstsetup(url="", username=""):
  22. # Get URL
  23. while True:
  24. if url != "":
  25. url = input(i18n.t("Server URL") + " (" + url + "): ") or url
  26. else:
  27. url = input(i18n.t("Server URL") + ": ")
  28. if validators.url(url):
  29. break
  30. else:
  31. print(i18n.t("That doesn't look right, try again."))
  32. # Get username
  33. while True:
  34. if username != "":
  35. username = input(i18n.t("Username") + " (" + username + "): ") or username
  36. else:
  37. username = input(i18n.t("Username") + ": ")
  38. if username != "":
  39. break
  40. # Get password
  41. while True:
  42. password = getpass(i18n.t("Password") + ": ")
  43. if password != "":
  44. break
  45. try:
  46. r = requests.post(url + "/api/ping", auth=(username, password))
  47. except:
  48. print(i18n.t("Could not connect to the server. Try again."))
  49. firstsetup()
  50. return
  51. if r.status_code == 401:
  52. print(i18n.t("Login incorrect, try again."))
  53. firstsetup(url)
  54. return
  55. try:
  56. resp = r.json()
  57. if resp["status"] == "ERROR":
  58. print(resp["msg"])
  59. firstsetup(url, username)
  60. return
  61. config["url"] = url
  62. config["username"] = username
  63. config["password"] = password
  64. saveconfig()
  65. return
  66. except ValueError:
  67. print(i18n.t("Login incorrect, try again."))
  68. firstsetup(url, username)
  69. return
  70. def loadnotes():
  71. global notes
  72. notes = api.do("getnotes")["notes"]
  73. def savenote(note):
  74. api.do("savenote", {
  75. "id": note["noteid"],
  76. "text": note["content"]
  77. })
  78. def editnote(note):
  79. global editor
  80. content = note["content"]
  81. f = tempfile.NamedTemporaryFile(mode='w+')
  82. f.write(content)
  83. f.flush()
  84. command = editor + " " + f.name
  85. status = os.system(command)
  86. f.seek(0, 0)
  87. text = f.read()
  88. f.close()
  89. assert not os.path.exists(f.name)
  90. note["content"] = text
  91. clearscreen()
  92. print(i18n.t("Saving..."))
  93. savenote(note)
  94. print(i18n.t("Note saved!"))
  95. def editmenu():
  96. global notes
  97. clearscreen()
  98. loadnotes()
  99. i = 1
  100. notelist = {}
  101. for note in notes:
  102. notelist[str(i)] = note
  103. print(chr(27) + "[0m", end='')
  104. print("\n\nNote #" + str(i) + ":")
  105. setbghexcolor(note["color"])
  106. setfgbybghex(note["color"])
  107. linecount = 0
  108. for line in note["content"].splitlines():
  109. if linecount > 5:
  110. print("\n(" + str(len(note["content"].splitlines())) + " more lines" + ")", end='')
  111. break
  112. print("\n " + line[0:70].ljust(70), end='')
  113. if len(line) > 70:
  114. print("...", end='')
  115. linecount += 1
  116. i += 1
  117. resetcolor()
  118. print("\n======================")
  119. noteid = input(i18n.t("Note to edit (M for main menu): "))
  120. if noteid.upper() == "M":
  121. clearscreen()
  122. return
  123. try:
  124. editnote(notelist[noteid])
  125. except KeyError:
  126. print(i18n.t("Invalid selection."))
  127. def newnote():
  128. global editor
  129. print()
  130. f = tempfile.NamedTemporaryFile(mode='w+')
  131. f.write("")
  132. f.flush()
  133. command = editor + " " + f.name
  134. status = os.system(command)
  135. f.seek(0, 0)
  136. text = f.read()
  137. f.close()
  138. assert not os.path.exists(f.name)
  139. if text == "":
  140. clearscreen()
  141. print(i18n.t("Nothing to do."))
  142. return
  143. print(i18n.t("Saving..."))
  144. api.do("savenote", {
  145. "text": text
  146. })
  147. print(i18n.t("Note created!"))
  148. def mainmenu():
  149. print("\n======================")
  150. print(i18n.t("Main Menu"))
  151. print("======================")
  152. print("E. " + i18n.t("View and edit notes"))
  153. print("C. " + i18n.t("Create a new note"))
  154. print("Q. " + i18n.t("Exit"))
  155. option = input(i18n.t("Choose an option: ")).upper()
  156. clearscreen()
  157. if option == "E":
  158. editmenu()
  159. elif option == "C":
  160. newnote()
  161. elif option == "Q":
  162. exit(0)
  163. else:
  164. print(i18n.t("Unrecognized selection, try again."))
  165. def main():
  166. print("NotePostCLI v0.1")
  167. if not checkconfig():
  168. print(i18n.t("No valid settings file found, running setup wizard."))
  169. firstsetup()
  170. else:
  171. loadconfig()
  172. while True:
  173. mainmenu()
  174. if __name__ == "__main__":
  175. main()