downloads.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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 is managing the downloads
  30. import os
  31. import time
  32. import json
  33. import threading
  34. import urllib.request
  35. from gi.repository import Gtk
  36. from gi.repository import Gdk
  37. from gi.repository import GLib
  38. from gi.repository import Pango
  39. from gi.repository import GdkPixbuf
  40. from subprocess import *
  41. from flbry import markdown
  42. from flbry import ui
  43. from flbry import fetch
  44. from flbry import settings
  45. from flbry import data_view
  46. from flbry import url
  47. from flbry import analytics
  48. def window(win):
  49. # The window of the dialog
  50. dwin = Gtk.Window()
  51. dwin.set_title("FastLBRY GTK: Downloads")
  52. dwin.set_size_request(500, 500)
  53. win.downloads["ui"] = {}
  54. box = Gtk.VBox()
  55. dwin.add(box)
  56. # I want to have a pie chart on the top to show
  57. # how much does LBRY effects the filesystem.
  58. settings = fetch.lbrynet("settings_get")
  59. download_folder = settings["download_dir"]
  60. lbry_folder = settings["data_dir"]
  61. def get_folder_size(Folder):
  62. size = 0
  63. for path, dirs, files in os.walk(Folder):
  64. for f in files:
  65. fp = os.path.join(path, f)
  66. size += os.path.getsize(fp)
  67. return size
  68. file_stats = os.statvfs(download_folder)
  69. downloads_size = get_folder_size(download_folder)
  70. lbry_data_size = get_folder_size(lbry_folder)
  71. full_disk = file_stats.f_blocks*file_stats.f_bsize
  72. free_space = file_stats.f_bavail*file_stats.f_bsize
  73. # We need to remove both downloads and lbry data from the ocupied space
  74. pie_data = {
  75. "Downloads":downloads_size,
  76. "LBRY Blobs / Data":lbry_data_size,
  77. "Unrelated to LBRY":full_disk-free_space-downloads_size-lbry_data_size,
  78. "Free Space":free_space
  79. }
  80. box.pack_start(analytics.pie_chart(win, pie_data, "Totals", converter=url.csize), 0, 0 , 0)
  81. scrl = Gtk.ScrolledWindow()
  82. scrl.set_hexpand(False)
  83. box.pack_start(scrl, True, True, 0)
  84. main_lbox = Gtk.VBox() # Needed for dynaimc loading
  85. scrl.add(main_lbox)
  86. draw_all(win, main_lbox, 1)
  87. dwin.show_all()
  88. def draw_all(win, main_lbox, page=1):
  89. #print("NEW PAGE", wasat)
  90. out = load(win, {"reverse":True,
  91. "page":page})
  92. lbox = Gtk.VBox() # The Main list box
  93. main_lbox.pack_start(lbox, 1,1,0)
  94. # Let's render it
  95. for item in reversed(out["items"]):
  96. sep = Gtk.HSeparator()
  97. lbox.pack_end(sep, 0,1,10)
  98. ############# FULL DATA ###############
  99. expand = Gtk.Expander(label=" Details: ")
  100. det_view = data_view.data_widget(item)
  101. expand.add(det_view)
  102. lbox.pack_end(expand, 1,0,0)
  103. ############ ITEM'S CONTROLLS #########
  104. hbox = Gtk.HBox() # The box of each item
  105. lbox.pack_end(hbox, 1,1,0)
  106. claim_id = item["claim_id"]
  107. try:
  108. thumb = item["metadata"]["thumbnail"]["url"]
  109. image = ui.load(win, ui.net_image_calculation, ui.net_image_render, thumb, 70, 70, "", True)
  110. hbox.pack_start(image, 0,0,5)
  111. except:
  112. pass
  113. rbox = Gtk.VBox() # The things excluding the thumbnail
  114. hbox.pack_start(rbox, 0,0,0)
  115. try:
  116. title = item["metadata"]["title"]
  117. except:
  118. title = item["claim_name"]
  119. #print("title", title)
  120. tlabel = Gtk.Label(title)
  121. tlabel.set_line_wrap_mode( Pango.WrapMode.WORD_CHAR )
  122. tlabel.set_line_wrap(True)
  123. rbox.pack_start(tlabel, 0,0,10)
  124. tbox = Gtk.HBox() # The toolbar with the buttons
  125. rbox.pack_start(tbox, 0,1,0)
  126. ############ RESOLVE BUTTON #######
  127. def on_resolve(w, claim_id, claim_name):
  128. link = claim_name+":"+claim_id
  129. win.resolve_tab = "new_tab"
  130. win.url.set_text(link)
  131. win.url.activate()
  132. dbutton = Gtk.Button()
  133. dbutton.connect("clicked", on_resolve, item["claim_id"], item["claim_name"])
  134. dbutton.set_relief(Gtk.ReliefStyle.NONE)
  135. dbox = Gtk.HBox()
  136. dbutton.add(dbox)
  137. dbox.pack_start(ui.icon(win, "system-search"), 0,0,0)
  138. dbox.pack_start(Gtk.Label("Resolve"), 0,0,0)
  139. tbox.pack_start(dbutton, 0,0,1)
  140. filename = item["download_path"]
  141. ############ DELETE BUTTON #################
  142. def on_delete(w, claim_id, filename, hbox, expand, sep):
  143. print("deleting",filename)
  144. url.delete_file(claim_id)
  145. try:
  146. os.remove(filename)
  147. except Exception as e:
  148. print(e)
  149. hbox.destroy()
  150. expand.destroy()
  151. sep.destroy()
  152. dbutton = Gtk.Button()
  153. dbutton.connect("clicked", on_delete, item["claim_id"], filename, hbox, expand, sep)
  154. dbutton.set_relief(Gtk.ReliefStyle.NONE)
  155. dbox = Gtk.HBox()
  156. dbutton.add(dbox)
  157. dbox.pack_start(ui.icon(win, "edit-delete"), 0,0,0)
  158. dbox.pack_start(Gtk.Label("Delete"), 0,0,0)
  159. tbox.pack_start(dbutton, 0,0,1)
  160. ############ PLAY BUTTON ###############
  161. if filename and os.path.exists(filename):
  162. def on_play(w, filename):
  163. Popen(["xdg-open", filename])
  164. dbutton = Gtk.Button()
  165. dbutton.connect("clicked", on_play, filename)
  166. dbutton.set_relief(Gtk.ReliefStyle.NONE)
  167. dbox = Gtk.HBox()
  168. dbutton.add(dbox)
  169. dbox.pack_start(ui.icon(win, "media-playback-start"), 0,0,0)
  170. dbox.pack_start(Gtk.Label("Launch"), 0,0,0)
  171. tbox.pack_start(dbutton, 0,0,1)
  172. if win.downloads["data"]["total_pages"] > page:
  173. lastthing(win, page, main_lbox)
  174. main_lbox.show_all()
  175. def lastthing(win, page, box):
  176. # I'm implementing it again and have no idea what I'm doing
  177. # This is needed to dynamically load more stuff as you scroll down.
  178. spinner_more = ui.icon(win, "loading", "gif")
  179. box.pack_start(spinner_more, False, False, 0)
  180. def draw_event(w, e):
  181. w.destroy()
  182. draw_all(win, box, page+1)
  183. spinner_more.connect("draw", draw_event)
  184. def load(win, args={}):
  185. print("LOADING:",args)
  186. out = fetch.lbrynet("file_list", args)
  187. if "data" not in win.downloads:
  188. win.downloads["data"] = out
  189. else:
  190. claims = []
  191. for i in win.downloads["data"]["items"]:
  192. claims.append(i["claim_id"])
  193. for i in out["items"]:
  194. if i["claim_id"] not in claims:
  195. win.downloads["data"]["items"].append(i)
  196. return out