settings.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. #####################################################################
  2. # #
  3. # THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE #
  4. # LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet ) #
  5. # FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk ) #
  6. # WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
  7. # IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
  8. # OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE. #
  9. # #
  10. # ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS #
  11. # (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK. #
  12. # YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
  13. # THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER #
  14. # VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG #
  15. # WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ). #
  16. # #
  17. # THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE #
  18. # NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
  19. # THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT #
  20. # SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
  21. # THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT. #
  22. # #
  23. # THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL #
  24. # FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE #
  25. # THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD #
  26. # TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT. #
  27. # #
  28. #####################################################################
  29. # This file will handle all kinds of settings
  30. import os
  31. import json
  32. from gi.repository import Gtk
  33. from flbry import ui
  34. from flbry import fetch
  35. from flbry import odysee
  36. from flbry import comments
  37. def get_settings_folder(flbry="flbry/"):
  38. try:
  39. data_dir = os.environ["XDG_DATA_HOME"] + "/" + flbry # Reducted back since it
  40. # broke too much and made
  41. # my settings appear in
  42. # $XDG_DATA_HOME folder
  43. # inside the repository.
  44. # WTF !!!
  45. except:
  46. data_dir = os.path.expanduser("~/.local/share/"+flbry)
  47. try:
  48. os.makedirs(data_dir)
  49. except:
  50. pass
  51. return data_dir
  52. def load():
  53. with open(get_settings_folder()+'config.json') as json_file:
  54. data = json.load(json_file)
  55. return data
  56. def save(data):
  57. with open(get_settings_folder()+'config.json', 'w') as fp:
  58. json.dump(data, fp, sort_keys=True, indent=4)
  59. def make_sure_file_exists():
  60. # Let's make some defaults
  61. defaults = {
  62. "GTK_icon_theme":"System Theme",
  63. "notifications":True,
  64. "auth_token": "",
  65. "autoconnect": False,
  66. "comment_api": "https://comments.odysee.com/api/v2",
  67. "lbrynet_binary": "flbry/lbrynet",
  68. "librarian_instance": "https://librarian.pussthecat.org/",
  69. "promote_fast_lbry_in_comments":False,
  70. "promote_fast_lbry_text": comments.BUTTON_GTK_PROMOTE_TEXT,
  71. "filter_tags":["mature", "sex", "porn"],
  72. "lock_password":"",
  73. "live_stream_player":"vlc",
  74. "default_tab":"following",
  75. "comments_auto_resize":True
  76. }
  77. # List of old and unneded or changed setting names. For example if
  78. # there was a spelling error in the key. This list exists for
  79. # backward compatibility, so users could update to the new version
  80. # without seeing two separate settings all of a sudden.
  81. old_and_bad = [
  82. "promote_fast_lbry_in_commnets" # issue #26 | Bad spelling
  83. ]
  84. # Let's write the Default theme.
  85. try:
  86. with open(get_settings_folder()+"config.json") as f:
  87. data = json.load(f)
  88. # Adding missing
  89. for i in defaults:
  90. if i not in data:
  91. data[i] = defaults[i]
  92. # Removing bad
  93. for i in old_and_bad:
  94. if i in data:
  95. del data[i]
  96. except Exception as e:
  97. data = defaults
  98. with open(get_settings_folder()+'config.json', 'w') as fp:
  99. json.dump(data, fp, sort_keys=True, indent=4)
  100. def dialogue(w, win):
  101. # This is the settings dialogue
  102. # Configuring the window
  103. dialogWindow = Gtk.Dialog("FastLBRY - Settings",
  104. buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
  105. Gtk.STOCK_OK, Gtk.ResponseType.OK),
  106. )
  107. dialogWindow.set_size_request(500,500)
  108. dialogWindow.set_default_icon_from_file("icon.png")
  109. mainbox = dialogWindow.get_content_area()
  110. # We will break the settings into tabs of various importances.
  111. notebook = Gtk.Notebook()
  112. notebook.set_scrollable(True)
  113. mainbox.pack_start(notebook, 1,1,0)
  114. #######################################################################
  115. # #
  116. # ACCOUNT / WALLET #
  117. # #
  118. #######################################################################
  119. scrl = Gtk.ScrolledWindow()
  120. box = Gtk.VBox()
  121. scrl.add(box)
  122. notebook.append_page(scrl, Gtk.Label("Account / Wallet"))
  123. # We need to get a list of all of the wallets on this system
  124. try:
  125. wallets = fetch.lbrynet("wallet_list")["items"]
  126. except:
  127. wallets = []
  128. for n, wallet in enumerate(wallets):
  129. wallet_frame = Gtk.Expander(label=wallet.get("name", ""))
  130. if n == 0:
  131. wallet_frame.set_expanded(True)
  132. box.pack_start(wallet_frame, 0,0,5)
  133. wbox = Gtk.VBox()
  134. wallet_frame.add(wbox)
  135. # Odysee sync button
  136. def sync_do(w):
  137. response = odysee.sync_ui(win)
  138. if "auth_token" in response:
  139. auth_e.set_text(response["auth_token"])
  140. win.settings["auth_token"] = response["auth_token"]
  141. save(win.settings)
  142. odysee_sync = Gtk.Button()
  143. odysee_sync.connect("clicked", sync_do)
  144. odysee_sync.set_relief(Gtk.ReliefStyle.NONE)
  145. obox = Gtk.HBox()
  146. odysee_sync.add(obox)
  147. obox.pack_start(Gtk.Image.new_from_file("icons/odysee.png"),0,0,2)
  148. obox.pack_start(Gtk.Label("Sync with Odysee"), 1,1,2)
  149. wbox.pack_start(odysee_sync, 0,0,2)
  150. box.pack_start(Gtk.HSeparator(), 0,0,10)
  151. # Auth Token
  152. auth_box = Gtk.HBox()
  153. box.pack_start(auth_box, 0,0,5)
  154. auth_box.pack_start(Gtk.Label("Authentication Token : "),0,0,5)
  155. auth_w, auth_e = ui.password_entry(win)
  156. auth_box.pack_start(auth_w, 1,1,5)
  157. auth_e.set_text(win.settings["auth_token"])
  158. # Lock Password
  159. lock_box = Gtk.HBox()
  160. box.pack_start(lock_box, 0,0,5)
  161. lock_box.pack_start(Gtk.Label("Wallet Lock Password : "),0,0,5)
  162. lock_w, lock_e = ui.password_entry(win)
  163. lock_box.pack_start(lock_w, 1,1,5)
  164. lock_e.set_text(win.settings["lock_password"])
  165. #######################################################################
  166. # #
  167. # COMMENTS #
  168. # #
  169. #######################################################################
  170. scrl = Gtk.ScrolledWindow()
  171. box = Gtk.VBox()
  172. scrl.add(box)
  173. notebook.append_page(scrl, Gtk.Label("Comments"))
  174. # Here will be the settings for comments.
  175. promote_box = Gtk.HBox()
  176. box.pack_start(promote_box, 0,0,5)
  177. promote_box.pack_start(Gtk.Label("Promote FastLBRY in Comments: "), 0,0,5)
  178. def hide_promotion_options(w, u):
  179. promote_options_box.set_visible(w.get_active())
  180. promote_fastlbry_switch = Gtk.Switch()
  181. promote_fastlbry_switch.connect("notify::active", hide_promotion_options)
  182. promote_fastlbry_switch.set_active(win.settings["promote_fast_lbry_in_comments"])
  183. promote_box.pack_end(promote_fastlbry_switch, 0,0,0)
  184. # Options of the promotion will come next. They are in a separate box, so I could
  185. # hide it when promotion is not activated.
  186. promote_options_box = Gtk.VBox()
  187. box.pack_start(promote_options_box, 0,0,5)
  188. type_of_promotion = Gtk.ComboBoxText()
  189. type_of_promotion.append_text( "Image Link" )
  190. type_of_promotion.append_text( "Text Link" )
  191. type_of_promotion.append_text( "Custom" )
  192. ptype_box = Gtk.HBox()
  193. promote_options_box.pack_start(ptype_box, 0,0,5)
  194. ptype_box.pack_start(Gtk.Label("Promotion Type: "), 0,0,5)
  195. ptype_box.pack_end(type_of_promotion, 0,0,5)
  196. def hide_custom_promotion(w):
  197. if type_of_promotion.get_active_text() == "Custom":
  198. pcustom_box.set_visible(True)
  199. else:
  200. pcustom_box.set_visible(False)
  201. type_of_promotion.connect("changed", hide_custom_promotion)
  202. pcustom_box = Gtk.HBox()
  203. promote_options_box.pack_start(pcustom_box, 0,0,5)
  204. pcustom_box.pack_start(Gtk.Label("Custom Promotion: "), 0,0,5)
  205. pcustom_entry = Gtk.Entry()
  206. pcustom_entry.set_text(win.settings["promote_fast_lbry_text"])
  207. pcustom_box.pack_end(pcustom_entry, 0,0,5)
  208. box.pack_start(Gtk.HSeparator(), 0,0,5)
  209. # Scaling of comments
  210. cscalebox = Gtk.HBox()
  211. cscalebox.pack_start(Gtk.Label(" Force-fit comments to window: "), 0,0,5)
  212. commentScaleSwitch = Gtk.Switch()
  213. commentScaleSwitch.set_active(win.settings["comments_auto_resize"])
  214. cscalebox.pack_end(commentScaleSwitch, 0,0,5)
  215. box.pack_start(cscalebox, 0,0,5)
  216. box.pack_start(Gtk.HSeparator(), 0,0,5)
  217. # Advanced commment settings
  218. advanced_frame = Gtk.Expander(label="Advanced Settings")
  219. box.pack_start(advanced_frame, 0,0,5)
  220. adbox = Gtk.VBox()
  221. advanced_frame.add(adbox)
  222. # Comment API setting. For talking on different comment servers.
  223. commentAPIbox = Gtk.HBox()
  224. adbox.pack_start(commentAPIbox, 0,0,5)
  225. commentAPIbox.pack_start(Gtk.Label(" Comment server: ") , 0,0,5)
  226. commentserverentry = Gtk.Entry()
  227. commentserverentry.set_text(win.settings["comment_api"])
  228. commentAPIbox.pack_start(commentserverentry , 1,1,5)
  229. #######################################################################
  230. # #
  231. # ALL THE REST #
  232. # #
  233. #######################################################################
  234. scrl = Gtk.ScrolledWindow()
  235. box = Gtk.VBox()
  236. scrl.add(box)
  237. notebook.append_page(scrl, Gtk.Label("Other Settings"))
  238. #######################################################################
  239. # #
  240. # THEMES SELECTOR #
  241. # #
  242. #######################################################################
  243. themes_setting = Gtk.ComboBoxText()
  244. #themes_setting.set_relief(Gtk.ReliefStyle.NONE)
  245. # Themes are laoded from folder in ./icons
  246. select = 0
  247. icon_themes = os.listdir(os.getcwd()+"/icons")
  248. icon_themes.append("System Theme")
  249. for n, theme in enumerate(icon_themes):
  250. themes_setting.append_text( theme )
  251. if win.settings["GTK_icon_theme"] == theme:
  252. select = n
  253. themes_setting.set_active(select)
  254. theme_box = Gtk.HBox()
  255. theme_box.pack_start(Gtk.Label(" Icon Theme (requires restart) : "), False, False, False)
  256. theme_box.pack_end(themes_setting, False, False, False)
  257. box.pack_start(theme_box, False, False, 5)
  258. # The default tab. Whether it's following or suggestions
  259. default_tab = Gtk.ComboBoxText()
  260. default_tab.append_text("Following")
  261. default_tab.append_text("Suggestions")
  262. if win.settings["default_tab"] == "suggest":
  263. default_tab.set_active(1)
  264. else:
  265. default_tab.set_active(0)
  266. default_box = Gtk.HBox()
  267. default_box.pack_start(Gtk.Label(" Default Tab : "), False, False, False)
  268. default_box.pack_end(default_tab, False, False, False)
  269. box.pack_start(default_box, False, False, 5)
  270. #######################################################################
  271. # #
  272. # ALL THE REST #
  273. # #
  274. #######################################################################
  275. # The settings are SHARED WITH FASTLBRY TERMINAL
  276. # The rest of settings are generated by what's available in the config
  277. # file. So there could be problems. First we need exclude list.
  278. exclude = ["GTK_icon_theme", # We have a separate thing for it
  279. "save_history", # Used by FastLBRY terminal, not interesting here
  280. "theme", # The theme of FastLBRY terminal
  281. "default_tip",
  282. "default_opener",
  283. "dev_mode",
  284. "default_editor",
  285. "music_player",
  286. "player",
  287. "markdown_reader",# In FastLBRY GTK we have a UI implementation for this
  288. "graph_force_ASCII", # Another FastLBRY Termianl only function
  289. "ignore_width_forcing", # FASTLBRY TERMINAL AGAIN
  290. "channel", # This one is set in the top pannel of the window
  291. "default_tab", # Implemented separately
  292. "auth_token", # [ Account / Wallet ] Tab
  293. "lock_password", # [ Account / Wallet ] Tab
  294. "promote_fast_lbry_in_comments", # [ Comments ] Tab
  295. "promote_fast_lbry_text", # [ Comments ] Tab
  296. "comment_api", # [ Comments ] Tab
  297. "comments_auto_resize" # [ Comments ] Tab
  298. ]
  299. parts = {}
  300. for name in win.settings:
  301. if name in exclude:
  302. continue
  303. parts[name] = {}
  304. parts[name]["box"] = Gtk.HBox()
  305. # I want to beutify the name for the setting
  306. pname = name.replace("_", " ")
  307. pname = " "+pname[0].upper()+pname[1:].lower()+" "
  308. parts[name]["box"].pack_start(Gtk.Label(pname), False, False, False)
  309. # Then depending on the type of the data itself, we are going to give
  310. # inputs
  311. if type(win.settings[name]) == str:
  312. parts[name]["entry"] = Gtk.Entry()
  313. parts[name]["entry"].set_text(win.settings[name])
  314. parts[name]["entry"].set_size_request(300,40)
  315. parts[name]["box"].pack_end(parts[name]["entry"], False, False, False)
  316. elif type(win.settings[name]) == bool:
  317. parts[name]["entry"] = Gtk.Switch()
  318. parts[name]["entry"].set_active(win.settings[name])
  319. parts[name]["box"].pack_end(parts[name]["entry"], False, False, False)
  320. elif type(win.settings[name]) == float:
  321. parts[name]["number"] = Gtk.Adjustment(win.settings[name],
  322. lower=0.0001,
  323. upper=1000000000,
  324. step_increment=0.1)
  325. parts[name]["entry"] = Gtk.SpinButton(adjustment=parts[name]["number"],
  326. digits=4)
  327. parts[name]["box"].pack_end(parts[name]["entry"], False, False, False)
  328. elif type(win.settings[name]) == int:
  329. parts[name]["number"] = Gtk.Adjustment(win.settings[name],
  330. lower=0,
  331. upper=1000000000,
  332. step_increment=4)
  333. parts[name]["entry"] = Gtk.SpinButton(adjustment=parts[name]["number"])
  334. parts[name]["box"].pack_end(parts[name]["entry"], False, False, False)
  335. elif type(win.settings[name]) == list:
  336. parts[name]["box"] = Gtk.VBox()
  337. parts[name]["box"].pack_start(Gtk.Label(pname), False, False, False)
  338. parts[name]["box"].pack_start( ui.tags_editor(win, win.settings[name]), True, True, 0)
  339. box.pack_start(parts[name]["box"], False, False, 5)
  340. # notifications_box = Gtk.HBox()
  341. # notifications_setting = Gtk.Switch()
  342. # notifications_setting.set_active(win.settings["notifications"])
  343. # notifications_box.pack_start(Gtk.Label(" Notifications: "), False, False, False)
  344. # notifications_box.pack_end(notifications_setting, False, False, False)
  345. # box.pack_start(notifications_box, False, False, False)
  346. #######################################################################
  347. # #
  348. # RUNING THE SETTINGS DIALOG #
  349. # #
  350. #######################################################################
  351. # Running the dialog
  352. mainbox.show_all()
  353. # Hide element
  354. if not win.settings["promote_fast_lbry_in_comments"]:
  355. promote_options_box.set_visible(False)
  356. if win.settings["promote_fast_lbry_text"] == comments.BUTTON_GTK_PROMOTE:
  357. type_of_promotion.set_active(0)
  358. elif win.settings["promote_fast_lbry_text"] == comments.BUTTON_GTK_PROMOTE_TEXT:
  359. type_of_promotion.set_active(1)
  360. else:
  361. type_of_promotion.set_active(2)
  362. response = dialogWindow.run()
  363. if response == Gtk.ResponseType.OK:
  364. # Here I want to overwrite all the setting to ones
  365. # chosen by the user.
  366. win.settings["GTK_icon_theme"] = themes_setting.get_active_text()
  367. win.settings["auth_token"] = auth_e.get_text()
  368. win.settings["lock_password"] = lock_e.get_text()
  369. win.settings["comment_api"] = commentserverentry.get_text()
  370. win.settings["comments_auto_resize"] = commentScaleSwitch.get_active()
  371. win.settings["promote_fast_lbry_in_comments"] = promote_fastlbry_switch.get_active()
  372. if type_of_promotion.get_active_text() == "Image Link":
  373. win.settings["promote_fast_lbry_text"] = comments.BUTTON_GTK_PROMOTE
  374. elif type_of_promotion.get_active_text() == "Text Link":
  375. win.settings["promote_fast_lbry_text"] = comments.BUTTON_GTK_PROMOTE_TEXT
  376. else:
  377. win.settings["promote_fast_lbry_text"] = pcustom_entry.get_text()
  378. if default_tab.get_active_text() == "Suggestions":
  379. win.settings["default_tab"] = "suggest"
  380. else:
  381. win.settings["default_tab"] = "following"
  382. for name in win.settings:
  383. if name in exclude:
  384. continue
  385. value = win.settings[name]
  386. if type(win.settings[name]) == str:
  387. value = parts[name]["entry"].get_text()
  388. elif type(win.settings[name]) == bool:
  389. value = parts[name]["entry"].get_active()
  390. elif type(win.settings[name]) == int:
  391. value = int(parts[name]["entry"].get_value())
  392. elif type(win.settings[name]) == float:
  393. value = parts[name]["entry"].get_value()
  394. win.settings[name] = value
  395. # Then we save everything.
  396. save(win.settings)
  397. if not win.settings["lock_password"]:
  398. win.lock_button.set_sensitive(False)
  399. else:
  400. win.lock_button.set_sensitive(True)
  401. dialogWindow.destroy()