123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- #####################################################################
- # #
- # 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 time
- import urllib.request
- import threading
- import json
- from subprocess import *
- from gi.repository import Gtk
- from gi.repository import Gdk
- from gi.repository import GLib
- 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
- from flbry import fetch
- from flbry import claim_search
- from flbry import comments
- def resolve(w, win, url):
-
- # This function will draw a widget of rsolved url
- #####################################################
- # RESOLVING PART ( NO GTK ) #
- #####################################################
- out = fetch.lbrynet("resolve",
- {"urls":[url]}
- )
- out = out[url]
- # Saving the resolved thing into the win for later use
- win.resolved = out
-
- # 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
- try:
- is_channel = "value_type" in out and out["value_type"] == "channel"
- percentage = downloaded(out["claim_id"])
- except:
- # If this fails we activate search
- return ["search", False, False, w, win, url]
-
- # make sure the url path starts with lbry://
- if not url.startswith("lbry://"):
- url = "lbry://"+url
- win.url.set_text(url)
- return [out, is_channel, percentage, w, win, url]
- def render_resolve(data):
- out, is_channel, percentage, w, win, url = data
- # It could be failed
- if out == "search":
- return ui.load(win, claim_search.find, claim_search.render, win, win.url.get_text())
-
-
- #####################################################
- # DRAWING PART ( GTK ) #
- #####################################################
- try:
- price = out["value"]["fee"]["amount"]
- except:
- price = 0
- try:
- currency = out["value"]["fee"]["currency"]
- except:
- currency = "LBC"
-
-
-
- box = Gtk.HBox()
- outbox = Gtk.VBox()
- #### THUMBNAIL ###
- thumb = ""
- try:
- thumb = out["value"]["thumbnail"]["url"]
- thumb_url = ui.image_save_name(thumb)
- def thumb_open(w):
- os.system("xdg-open "+thumb_url)
- thumb_button = Gtk.Button()
- thumb_button.set_tooltip_text(thumb)
- if is_channel:
- thumb_image = ui.load(win, ui.net_image_calculation, ui.net_image_render, thumb, 150, "", True)
- else:
- thumb_image = ui.load(win, ui.net_image_calculation, ui.net_image_render, thumb, 400, "", 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)
- except:
- pass
-
- 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_calculation, ui.net_image_render, 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:
- name_channel_box.pack_start(ui.go_to_channel(win, out["signing_channel"]),False,False,False)
-
- # name it self
- title = out["name"]
- 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(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)
- #filesize
- labeltext = "Download"
- if price:
- labeltext = "Buy for "+str(price)+" "+currency
- try:
- filesize = out["value"]["source"]["size"]
- labeltext = labeltext + " ("+csize(filesize)+")"
- except:
- filesize = 0
-
- download_box.pack_start(Gtk.Label(labeltext), 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" and price == 0:
- # We download it first
-
- playout = fetch.lbrynet("get", {"uri":url, "save_file":True})
- # 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)
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "text-plain"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Read Article "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(md_scrl, detailsbox)
- # 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)
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "text-markdown"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Source of Article "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(md_scrl, detailsbox)
-
- except Exception as e:
- print("FUCKING ERROR")
- print(e)
- print()
- # Channel Uploads / Publications
-
- if is_channel:
- uploads_box = ui.load(win, claim_search.find, claim_search.render, win, "", [out["claim_id"]], )
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "folder-remote"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Publications "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(uploads_box, detailsbox)
-
-
- ##### 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()
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "text-plain"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Description "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(description_scrl, detailsbox)
-
- description_box.pack_start(description_scrl, False, False, False)
- description_scrl.add(description_field)
- except:
- pass
- ######## COMMENTS ########
-
- com_box = Gtk.VBox()
- com_scrl = Gtk.ScrolledWindow()
- comments_widget = ui.load(win, comments.list_comments, comments.render_comments, win, out["claim_id"], )
- com_scrl.add(comments_widget)
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "message-new"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Comments "), True, True, True)
- detailsbox.show_all()
- com_box.pack_start(comments.comment_input(win), False, False, 0)
- com_box.pack_start(com_scrl, True, True, 0)
- notebook.append_page(com_box, detailsbox)
-
- ##### Details #######
- # Almost like Raw Data but shows only the important stuff
-
- details = {"LBRY URL: ":url,
- "Price: ":str(price)+" "+str(currency)}
- try:
- details["Claim ID: "] = out["claim_id"]
- except:
- pass
- try:
- details["Upload Bid: "] = out["amount"]+" LBC"
- except:
- pass
- try:
- details["Support: "] = out["meta"]["support_amount"]+" LBC"
- except:
- pass
-
-
- try:
- details["Filename: "] = out["value"]["source"]["name"]
- except:
- pass
- try:
- details["File Size:"] = csize(filesize)
- except:
- pass
- try:
- details["License: "] = out["value"]["license"]
- except:
- pass
- try:
- details["Released at: "] = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(out["value"]["release_time"])))
- except:
- pass
-
- det_scrl = Gtk.ScrolledWindow()
- det_view = data_view.data_widget(details)
- det_scrl.add(det_view)
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "emblem-information"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Details "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(det_scrl, detailsbox)
-
- ##### Raw Data #######
- raw_scrl = Gtk.ScrolledWindow()
- raw_view = data_view.data_widget(out)
- raw_scrl.add(raw_view)
- detailsbox = Gtk.HBox()
- detailsbox.pack_start(ui.icon(win, "emblem-warning"), False, False, False)
- detailsbox.pack_start(Gtk.Label(" Extra Details "), True, True, True)
- detailsbox.show_all()
- notebook.append_page(raw_scrl, detailsbox)
-
-
- #outbox.show_all()
- return outbox
- 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])
- out = fetch.lbrynet("file_list", {"claim_id":claim_id})
- #print(out, '\n\n')
-
- 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])
- out = fetch.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])
- fetch.lbrynet("file_delete", {"claim_id":claim_id})
- def start_downloading(url):
- out = fetch.lbrynet("get", {"uri":url, "save_file":True})
-
- 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.
- def update(fraction):
- 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)
-
- while True:
-
- fraction = downloaded(claim_id)
- GLib.idle_add(update, fraction)
- time.sleep(2) # The new algorithm is too fast LOL
- if not win.check_download_daemon_keep_alive:
- return
- def csize(x):
- x = float(x)
- l = ["B","KB", "MB", "GB", "TB"]
- for i in range(5):
- if x > 1024:
- x = x / 1024
- else:
- return str(round(x, 2))+" "+l[i]
- return str(round(x, 2))+" "+l[i]
|