123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- #####################################################################
- # #
- # THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE #
- # LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet ) #
- # FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk ) #
- # WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
- # IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
- # OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE. #
- # #
- # ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS #
- # (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK. #
- # YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
- # THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER #
- # VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG #
- # WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ). #
- # #
- # THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE #
- # NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
- # THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT #
- # SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
- # THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT. #
- # #
- # THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL #
- # FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE #
- # THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD #
- # TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT. #
- # #
- #####################################################################
- import os
- import urllib.request
- import threading
- import json
- from subprocess import *
- from gi.repository import Gtk
- from gi.repository import Gdk
- from gi.repository import Pango
- from gi.repository import GdkPixbuf
- from PIL import Image, ImageSequence
- from flbry import markdown
- from flbry import data_view
- from flbry import ui
- def resolve(w, win, outbox, url):
-
- # This function will draw a widget of rsolved url
- out = check_output(["flbry/lbrynet",
- "resolve", url])
- raw_data = out.decode("utf-8")
-
- # Now we want to parse the json
- try:
- out = json.loads(out)
- out = out[url]
- except:
- print("Resolve Failed")
- return False
- is_channel = "value_type" in out and out["value_type"] == "channel"
- percentage = downloaded(out["claim_id"])
-
- # make sure the url path starts with lbry://
- if not url.startswith("lbry://"):
- url = "lbry://"+url
- win.url.set_text(url)
-
- box = Gtk.HBox()
- #### THUMBNAIL ###
- thumb = ""
- try:
- thumb = out["value"]["thumbnail"]["url"]
- except Exception as e:
- print("Error loading thumbnail: ", e)
-
- def thumb_open(w):
- os.system("xdg-open /tmp/flbry_thumbnail")
-
- thumb_button = Gtk.Button()
- thumb_button.set_tooltip_text(thumb)
- if is_channel:
- thumb_image = ui.load(win, ui.net_image, thumb, 150, "/tmp/flbry_thumbnail", True)
- else:
- thumb_image = ui.load(win, ui.net_image, thumb, 400, "/tmp/flbry_thumbnail", True)
- thumb_button.add(thumb_image)
- thumb_button.set_relief(Gtk.ReliefStyle.NONE)
- thumb_button.connect("clicked", thumb_open)
-
- box.pack_start(thumb_button, False, False, False)
- outbox.pack_start(box, False, False, False)
- from_right_to_thumbnail = Gtk.VBox()
- box.pack_end(from_right_to_thumbnail, True, True, False)
- # If channel load banner
- if is_channel:
- if "cover" in out["value"]:
- channel_banner = ui.load(win, ui.net_image, out["value"]["cover"]["url"], False, "", True)
- channel_scroll = Gtk.ScrolledWindow()
- channel_scroll.set_size_request(400,150)
- channel_scroll.add_with_viewport(channel_banner)
- from_right_to_thumbnail.pack_start(channel_scroll, False, False, False)
- else:
- try:
- channel_scroll.destroy()
- except:
- pass
-
-
- #### NAME / CHANNEL ####
- the_packing_box = from_right_to_thumbnail
- if is_channel:
- the_packing_box = outbox
-
- name_channel_box = Gtk.VBox()
- the_packing_box.pack_start(name_channel_box, False, False, False)
- # Channel
- if "signing_channel" in out:
- # Get channel name
- try:
- channel_name = out["signing_channel"]["value"]["title"]
- except:
- channel_name = out["signing_channel"]["name"]
- def channel_resolve(w):
- win.url.set_text(out["signing_channel"]["canonical_url"])
- win.url.activate()
-
- channel_button = Gtk.Button()
- channel_button.set_tooltip_text(out["signing_channel"]["canonical_url"])
- channel_button.connect("clicked", channel_resolve)
- channel_button.set_relief(Gtk.ReliefStyle.NONE)
- channel_button_box = Gtk.HBox()
- channel_button.add(channel_button_box)
- # If channel thumbnail exists.
- try:
- channel_thumb = ui.load(win, ui.net_image, out["signing_channel"]["value"]["thumbnail"]["url"], 40 , "", False)
- channel_button_box.pack_start(channel_thumb, False,False,False)
- except:
- pass
-
- channel_button_box.pack_start(Gtk.Label(channel_name), False, False, False)
- name_channel_box.pack_start(channel_button,False,False,False)
-
- # name it self
- title = "[no title]"
- try:
- title = out["value"]["title"]
- except:
- pass
- title_label = Gtk.Label()
- title_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
- title_label.set_line_wrap(True)
- title_label.set_markup('<span size="x-large"> '+title+'</span> ')
- title_label.set_selectable(True)
- title_label.set_css_name("")
- name_channel_box.pack_start(title_label, False, False, False)
- ################# TOOL BAR ##################
- toolbox = Gtk.HBox()
- the_packing_box.pack_start(toolbox, False, False,False)
- if not is_channel:
- def download_action(w):
- start_downloading(out["permanent_url"])
-
- download_button = Gtk.Button()
- download_button.connect("clicked", download_action)
- download_button.set_relief(Gtk.ReliefStyle.NONE)
- download_box = Gtk.HBox()
- download_button.add(download_box)
- download_icon = ui.icon(win, "download")
- download_box.pack_start(download_icon, False, False, False)
- download_box.pack_start(Gtk.Label("Download"), False, False, False)
- toolbox.pack_start(download_button, False,False,False)
- download_bar = Gtk.ProgressBar()
- the_packing_box.pack_start(download_bar, False, False,False)
- def delete_action(w):
- filename = get_downloaded_file(out["claim_id"])
- delete_file(out["claim_id"])
- try:
- os.remove(filename)
- except:
- pass
-
- delete_button = Gtk.Button()
- delete_button.connect("clicked", delete_action)
- delete_button.set_relief(Gtk.ReliefStyle.NONE)
- delete_box = Gtk.HBox()
- delete_button.add(delete_box)
- delete_icon = ui.icon(win,"delete")
- delete_box.pack_start(delete_icon, False, False, False)
- delete_box.pack_start(Gtk.Label("Delete"), False, False, False)
- toolbox.pack_start(delete_button, False,False,False)
- def launch_action(w):
- Popen(["xdg-open", get_downloaded_file(out["claim_id"])])
- launch_button = Gtk.Button()
- launch_button.connect("clicked", launch_action)
- launch_button.set_relief(Gtk.ReliefStyle.NONE)
- launch_box = Gtk.HBox()
- launch_button.add(launch_box)
- launch_icon = ui.icon(win, "launch")
- launch_box.pack_start(launch_icon, False, False, False)
- launch_box.pack_start(Gtk.Label("Launch"), False, False, False)
- toolbox.pack_start(launch_button, False,False,False)
- win.check_download_daemon_keep_alive = True
-
- t = threading.Thread(target=downloading_check_thread, args=(win, out["claim_id"],download_button, delete_button, launch_button, download_bar))
- t.setDaemon(True)
- t.start()
- def kill_daemon(w):
- win.check_download_daemon_keep_alive = False
- download_button.connect("destroy", kill_daemon)
-
- ########### BOTTOM NOTEBOOK ##############
- notebook = Gtk.Notebook()
- outbox.pack_start(notebook, True, True,False)
- # If article read article
- try:
- if out["value"]["source"]["media_type"] == "text/markdown":
- playout = check_output(["flbry/lbrynet",
- "get", url])
- # Parsing the Json
- playout = json.loads(playout)
- md_text = open(playout['download_path'])
- md_text = md_text.read()
- # Markdown covenreted
- md_scrl = Gtk.ScrolledWindow()
- md_view = Gtk.TextView()
- md_view.set_wrap_mode(Gtk.WrapMode.WORD )
- md_buffer = md_view.get_buffer()
- md_view.set_editable(False)
- md_scrl.add(md_view)
- md_buffer.set_text(md_text)
- markdown.convert(win, md_view)
- notebook.append_page(md_scrl, Gtk.Label("Read Article"))
- # Markdown source
- md_scrl = Gtk.ScrolledWindow()
- md_view = Gtk.TextView()
- #md_view.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0.2,0.2,0.2, 1))
- #md_view.override_color(Gtk.StateType.NORMAL, Gdk.RGBA(0.9,0.9,0.9, 1))
- md_view.override_font(Pango.FontDescription("Monospace"))
- md_view.set_wrap_mode(Gtk.WrapMode.WORD )
- md_buffer = md_view.get_buffer()
- md_view.set_editable(False)
- md_scrl.add(md_view)
- md_buffer.set_text(md_text)
- notebook.append_page(md_scrl, Gtk.Label("Source Code"))
-
- except:
- pass
- # Channel Uploads / Publications
-
- if is_channel:
- uploads_box = Gtk.VBox()
- notebook.append_page(uploads_box, Gtk.Label("Publications"))
-
-
- ##### DESCRIPTION ####
-
- try:
- description_scrl = Gtk.ScrolledWindow()
- description_scrl.set_size_request(500,200)
- description_field = Gtk.TextView()
- description_field.set_wrap_mode(Gtk.WrapMode.WORD )
- description_field.set_editable(False)
- description_buffer = description_field.get_buffer()
- description_buffer.set_text(out["value"]["description"])
- markdown.convert(win, description_field)
- description_box = Gtk.VBox()
- notebook.append_page(description_scrl, Gtk.Label("Description"))
-
- description_box.pack_start(description_scrl, False, False, False)
- description_scrl.add(description_field)
- except:
- pass
- ##### Raw Data #######
- raw_scrl = Gtk.ScrolledWindow()
- raw_view = data_view.data_widget(out)
- raw_scrl.add(raw_view)
- notebook.append_page(raw_scrl, Gtk.Label("Raw Data"))
-
- outbox.show_all()
- return True
- def downloaded(claim_id):
- # Returns a fraction ( from 0 to 1 ) of the download
- # percentage. If it's a 0, we can use it to display
- # the download button.
- out = check_output(["flbry/lbrynet",
- "file", "list", "--claim_id="+claim_id])
- try:
- out = json.loads(out)
- out = out["items"][0]
- if out["status"] == "finished":
- return 1
- else:
- return out["written_bytes"] / out["total_bytes"]
-
- except:
- return 0
- def get_downloaded_file(claim_id):
- out = check_output(["flbry/lbrynet",
- "file", "list", "--claim_id="+claim_id])
- try:
- out = json.loads(out)
- out = out["items"][0]
- return out["download_path"]
- except:
- return ""
- def delete_file(claim_id):
- check_output(["flbry/lbrynet",
- "file", "delete", "--claim_id="+claim_id])
- def start_downloading(url):
- check_output(["flbry/lbrynet",
- "get", url])
-
- def downloading_check_thread(win, claim_id,
- download_button,
- delete_button,
- launch_button,
- progress_bar):
- # This is a thread that will toggle buttons on/off
- # based on a curretly downloading file.
- while True:
- fraction = downloaded(claim_id)
- if not fraction: # if it's 0
- download_button.set_visible(True)
- delete_button.set_visible(False)
- launch_button.set_visible(False)
- progress_bar.set_visible(False)
- else:
- download_button.set_visible(False)
- delete_button.set_visible(True)
- launch_button.set_visible(True)
- progress_bar.set_visible(True)
- progress_bar.set_fraction(fraction)
- if fraction == 1:
- progress_bar.set_visible(False)
- if not win.check_download_daemon_keep_alive:
- return
|