123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711 |
- #####################################################################
- # #
- # 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 time
- import json
- import threading
- import urllib.request
- 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 flbry import markdown
- from flbry import ui
- from flbry import fetch
- from flbry import settings
- # TODO: Get rid of this string and use win.settings["comment_api"] instead
- comments_api = "https://comments.odysee.com/api/v2"
- # This is going into the end of comments to promote FastLBRY GTK
- BUTTON_GTK_PROMOTE = "\n\n[![](https://player.odycdn.com/api/v4/streams/free/button_GTK/d025c8ec2cdb5122a85b374b7bc453ba11d9409d/6526ef)](https://notabug.org/jyamihud/FastLBRY-GTK)"
- def list_comments( win, data, page=1, megabox=False):
- claim_id = data["claim_id"]
-
- # gets list of comment
-
- params = {
- "claim_id": claim_id,
- "page": page,
- # "page_size": page_size,
- "sort_by": 0,
- "top_level": False,
- }
- time.sleep(1) # too fast
-
- out = comment_request("comment.List", params)
- out = get_reactions(out)
- return [win, out, data, megabox]
- def render_single_comment(win, box, i):
- claim_id = i["claim_id"]
- items = win.commenting[claim_id]["data"]["result"]["items"]
-
- # Like / Dislike ratio
- reactionbox = Gtk.HBox()
- like_dislike_ratio_box = Gtk.VBox()
- like_dislike_box = Gtk.HBox()
- likes = i.get("reactions", {}).get("like", 0)
- like = Gtk.ToggleButton(" 👍 "+str(likes)+" ")
- like.set_relief(Gtk.ReliefStyle.NONE)
- like_dislike_box.pack_start(like, False, False, 0)
- dislikes = i.get("reactions", {}).get("dislike", 0)
- dislike = Gtk.ToggleButton(" 👎 "+str(dislikes)+" ")
- dislike.set_relief(Gtk.ReliefStyle.NONE)
- like_dislike_box.pack_start(dislike, False, False, 0)
- like_dislike_ratio_box.pack_start(like_dislike_box, False, False, False)
- try:
- frac = likes / (likes + dislikes)
- except:
- frac = 0
- ratio_bar = Gtk.ProgressBar()
- ratio_bar.set_fraction(frac)
- like_dislike_ratio_box.pack_start(ratio_bar, True, True,0)
- reactionbox.pack_start(like_dislike_ratio_box, False, False, False)
- ########### REPLY ############
- def reply_set(w):
- for ch in win.commenting[claim_id]["reply"]["box"].get_children():
- ch.destroy()
- win.commenting[claim_id]["reply"]["to"] = i["comment_id"]
- reply_frame = Gtk.Frame(label=" Replying to: ")
- reply_frame.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
- reply_box = Gtk.HBox()
- reply_frame.add(reply_box)
- chbox = Gtk.HBox()
- channel_button = ui.load(win, resolve_channel, render_channel, win, i["channel_url"])
- chbox.pack_start(channel_button, False, False, 0)
- reply_box.pack_start(chbox, False, False, 4)
- comment_label = Gtk.Label(i["comment"].split("\n")[0][:100]+" ...")
- comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
- comment_label.set_line_wrap(True)
- reply_box.pack_start(comment_label, False, False, 10)
-
- win.commenting[claim_id]["reply"]["box"].pack_start(reply_frame, True, True, 5)
- ##### DELETE REPLY ####
- def delete_set(w):
- for ch in win.commenting[claim_id]["reply"]["box"].get_children():
- ch.destroy()
- win.commenting[claim_id]["reply"]["to"] = ""
-
- delete = Gtk.Button()
- delete.connect("clicked", delete_set)
- delete.set_relief(Gtk.ReliefStyle.NONE)
- delete.add(ui.icon(win, "edit-delete"))
- win.commenting[claim_id]["reply"]["box"].pack_end(delete, False, False, 0)
-
-
- win.commenting[claim_id]["reply"]["box"].show_all()
- reply = Gtk.Button(" Reply ")
- reply.set_relief(Gtk.ReliefStyle.NONE)
- reply.connect("clicked", reply_set)
- reactionbox.pack_end(reply, False, False, False)
- box.pack_end(reactionbox, False, False, 0)
-
- comment_text = i["comment"]
- supporter = False
- if BUTTON_GTK_PROMOTE in comment_text:
- supporter = True
- comment_text = comment_text.replace(BUTTON_GTK_PROMOTE, "")
-
- def force_size(w, e):
- w.queue_resize()
- commentbox = Gtk.Frame()
- commentbox.set_border_width(5)
- comment_field = Gtk.TextView()
- comment_field.connect("draw", force_size)
- comment_field.set_wrap_mode(Gtk.WrapMode.WORD_CHAR )
- comment_field.set_editable(False)
- comment_field.set_hexpand(False)
- comment_buffer = comment_field.get_buffer()
- comment_buffer.set_text(comment_text)
- markdown.convert(win, comment_field, imwidth=200)
- commentbox.add(comment_field)
- box.pack_end(commentbox, True, True, 0)
-
- # comment_label = Gtk.Label(comment_text)
- # comment_label.set_selectable(True)
- # comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
- # comment_label.set_line_wrap(True)
- # comment_label.set_max_width_chars(20)
- # box.pack_end(comment_label, True, True, 10)
- def resolve_channel(win, url):
- out = fetch.lbrynet("resolve", {"urls":url})
- out = out[url]
- return [win, out]
- def render_channel(out):
- win, out = out
- return ui.go_to_channel(win, out)
- # Sometimes it's a reply
- if "parent_id" in i:
- for b in items:
- if b["comment_id"] == i["parent_id"]:
- expand = Gtk.Expander(label=" In Reply to: ")
- reply_frame = Gtk.Frame()
- reply_frame.set_border_width(10)
- expand.add(reply_frame)
- reply_frame.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
- reply_box = Gtk.VBox()
- reply_frame.add(reply_box)
- render_single_comment(win, reply_box, b)
-
- # if "channel_url" in b:
- # chbox = Gtk.HBox()
- # channel_button = ui.load(win, resolve_channel, render_channel, win, b["channel_url"])
- # chbox.pack_start(channel_button, False, False, 0)
- # reply_box.pack_start(chbox, True, False, 4)
- # comment_field = Gtk.TextView()
- # comment_field.set_wrap_mode(Gtk.WrapMode.WORD )
- # comment_field.set_editable(False)
- # comment_field.set_hexpand(False)
- # comment_buffer = comment_field.get_buffer()
- # comment_buffer.set_text(b["comment"].replace(BUTTON_GTK_PROMOTE, ""))
- # markdown.convert(win, comment_field, imwidth=200)
-
- # comment_label = Gtk.Label(b["comment"].replace(BUTTON_GTK_PROMOTE, ""))
- # comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
- # comment_label.set_line_wrap(True)
- # comment_label.set_max_width_chars(20)
-
- #reply_box.pack_start(comment_field, True, True, 10)
- box.pack_end(expand, True, True, 10)
- break
- # each channel will need to be resolved on fly
- if "channel_url" in i:
- chbox = Gtk.HBox()
- channel_button = ui.load(win, resolve_channel, render_channel, win, i["channel_url"])
- chbox.pack_start(channel_button, False, False, 0)
- if "support_amount" in i and i["support_amount"]:
- chbox.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
- chbox.pack_start(Gtk.Label(" "+str(i["support_amount"])+" LBC"), False, False, 0)
- if supporter:
- chbox.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
- chbox.pack_start(Gtk.Label(" Promoter of FastLBRY "), False, False, 0)
-
-
- box.pack_end(chbox, False, False, 4)
- box.pack_end(Gtk.HSeparator(), False, False, 0)
- def render_comments(out, megabox=False):
-
- win, out, data, megabox = out
- if not megabox:
- megabox = Gtk.VBox()
- megabox.show_all()
- # renders a list of comments
-
- box = Gtk.VBox()
- box.set_hexpand(False)
- # I want to setup a little daemon to update the comments
- # automatically
- claim_id = data["claim_id"]
- try:
- the_title = data["value"]["title"]
- except:
- the_title = data["name"]
-
- if out["result"]["page"] == 1: # If it's the first page
-
- win.commenting[claim_id]["box"] = box
- win.commenting[claim_id]["data"] = out
- win.check_comment_daemon_keep_alive = True
- load_thread = threading.Thread(target=comment_daemon, args=[win, data, the_title])
- load_thread.setDaemon(True)
- load_thread.start()
- def kill_daemon(w):
- win.check_comment_daemon_keep_alive = False
- box.connect("destroy", kill_daemon)
-
- try:
- items = out["result"]["items"]
- for i in items:
- if i not in win.commenting[claim_id]["data"]["result"]["items"]:
- win.commenting[claim_id]["data"]["result"]["items"].append(i)
- except:
- items = []
- for i in reversed(items):
-
- #print("\n\n:::::::::::::::::\n\n", i)
- render_single_comment(win, box, i)
-
- box.show_all()
- # The top level box containing about 50 comments
- megabox.pack_start(box, False, False, 0)
- lastthing(win, out, data, megabox)
- megabox.show_all()
-
- return megabox
- def comment_daemon(win, data, the_title=""):
- # This function will be a daemon for the current comment system to
- # load all new comments that happen while the user it on the page.
- claim_id = data["claim_id"]
-
- while win.commenting[claim_id]["keep_alive"]:
-
- time.sleep(2) # Update every two seconds ( I don't want it to crash )
- n = win.commenting[claim_id]["data"]
- try:
- claim_id = n["result"]["items"][0]["claim_id"]
- except:
- n["result"]["items"] = []
- continue
- win, out, data, megabox = list_comments(win, data)
- ##### LOGIC OF ADDING MISSING COMMENTS INTO THE BOX ####
- for i in reversed(out["result"]["items"]):
- if i not in n["result"]["items"]:
- ids = []
- for b in n["result"]["items"]:
- ids.append(b["comment_id"])
- ######## FOUND A NEW COMMENT #######
-
- if i["comment_id"] not in ids:
- try:
- channel = i["channel_name"]
- except:
- channel = "[anonymous]"
- text = i["comment"]
- print("COMMENT FROM ", channel, "IS", text)
- force = win.resolved["claim_id"] != claim_id
- ui.notify(win, channel+" Commented on "+the_title, text, force=force)
- win.commenting[claim_id]["data"]["result"]["items"].append(i)
- print(i["comment_id"])
- box = win.commenting[claim_id]["box"]
- def render(win, box, i):
- render_single_comment(win, box, i)
- box.show_all()
- GLib.idle_add(render, win, box, i)
- def br(w):
- if not win.commenting[claim_id]["listen"]:
- win.commenting[claim_id]["keep_alive"] = False
- win.commenting[claim_id]["box"].connect("destroy", br)
- def lastthing(win, out, data, megabox):
- # This will hack itself to load more comments when you reached the end.
-
- spinner_more = ui.icon(win, "loading", "gif")
-
- megabox.pack_start(spinner_more, False, False, 0)
-
- def draw_event(w, e):
- print("EVENT")
- w.destroy()
-
- try:
- claim_id = out["result"]["items"][0]["claim_id"]
- page = out["result"]["page"] + 1
- ui.load(win, list_comments, render_comments, win, data, page, megabox, wait=False )
-
- except Exception as e:
- print("ERROR IS:", e)
-
-
- spinner_more.connect("draw", draw_event)
-
-
- def get_reactions(out):
- # Adds reactions list to the out
- try:
- claim_id = out["result"]["items"][0]["claim_id"]
- ids = ""
- for i in out["result"]["items"]:
- ids = ids + i["comment_id"] + ","
- ids = ids[:-1]
- except:
- return out
-
- rec = {
- "claim_id":claim_id,
- "comment_ids":ids}
- rec = comment_request("reaction.List", rec, addition="?m=reaction.List")
- for i in out["result"]["items"]:
- try:
- i["reactions"] = rec["result"]["others_reactions"][i["comment_id"]]
- except:
- pass
-
- return out
-
- def comment_request(method: str, params: dict, addition=""):
- """
- Sends a request to the comment API
- """
- data = {
- "method": method,
- "id": 1,
- "jsonrpc":"2.0",
- "params": params
- }
- data = json.dumps(data).encode()
- headers = {
- "Content-Type": "application/json"
- }
-
-
- try:
- req = urllib.request.Request(comments_api, data, headers)
- res = urllib.request.urlopen(req)
- out = res.read().decode()
- return json.loads(out)
- except Exception as e:
- print("COMMENT ERROR:", e)
- return
- def comment_input(win, claim_id):
- # claim_id = win.resolved["claim_id"]
-
- # This is the input for new comments.
- vbox = Gtk.VBox()
- pannel = Gtk.HBox()
- vbox.pack_start(pannel, False, False, False)
- ################## LISTEN BUTTON ###############
- try:
- give_listen = win.commenting[claim_id]["listen"]
- except:
- give_listen = False
-
- win.commenting[claim_id] = {"box": False,
- "data":{},
- "listen":give_listen,
- "keep_alive":True}
-
- if win.settings["notifications"]:
-
- lbox = Gtk.HBox()
- lbox.pack_start(Gtk.Label(" Listen "), False, False, False)
- listen = Gtk.Switch()
-
- def lclick(w, u):
- win.commenting[claim_id]["listen"] = listen.get_active()
- try:
- listen.set_active(win.commenting[claim_id]["listen"])
- except Exception as e:
- print("Switch is:", e)
- listen.connect("notify::active", lclick)
- lbox.pack_start(listen, False, False, False)
- pannel.pack_start(lbox, False, False, False)
-
- if win.channel:
- ############# BOX FOR REPLIES ##############
- # There will be a hidden box for replies. And when
- # the user presses the 'reply' button on any
- # of the current comments, it will fill up the box.
- win.commenting[claim_id]["reply"] = {"box":Gtk.HBox(),
- "to":""}
- vbox.pack_start( win.commenting[claim_id]["reply"]["box"], False, False, False)
- ############### SEND BUTTON ###################
-
- def send_do(w):
- tb = view.get_buffer()
- message = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True)
- tb.set_text("")
- send_comment(win, message, claim_id)
-
- send = Gtk.Button()
- send.connect("clicked", send_do)
- send.set_relief(Gtk.ReliefStyle.NONE)
- sendbox = Gtk.HBox()
- sendbox.pack_start(ui.icon(win, "document-send"), False, False, 0)
- sendbox.pack_start(Gtk.Label(" Send "), False, False, 0)
- pannel.pack_end(send, False, False, False)
- send.add(sendbox)
-
- ############## TEXT INPUT ##############
- inputbox = Gtk.HPaned()
- inputbox.set_position(500)
- vbox.pack_start(inputbox, False, False, False)
-
- frame = Gtk.Frame()
- scrl = Gtk.ScrolledWindow()
- view = Gtk.TextView()
- view.override_font(Pango.FontDescription("Monospace"))
- view.set_wrap_mode(Gtk.WrapMode.WORD)
- scrl.set_size_request(100,100)
- scrl.add(view)
- #view.set_size_request(100,100)
- frame.add(scrl)
- inputbox.add1(frame)
- ############## MARKDOWN PREVIEW ##############
- commentbox = Gtk.Frame()
- scrl2 = Gtk.ScrolledWindow()
- comment_field = Gtk.TextView()
- comment_field.set_wrap_mode(Gtk.WrapMode.WORD )
- comment_field.set_editable(False)
- comment_field.set_hexpand(False)
- comment_buffer = comment_field.get_buffer()
- scrl2.add(comment_field)
- commentbox.add(scrl2)
- inputbox.add2(commentbox)
- def on_changed(w):
- tb = view.get_buffer()
- message = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True)
- comment_buffer.set_text(message)
- markdown.convert(win, comment_field, 200)
- comment_field.show_all()
- # Scrolling to the end
- # TODO: Make it scroll to the character
- adj = scrl2.get_vadjustment()
- adj.set_value( adj.get_upper() )
-
- view.get_buffer().connect("changed", on_changed)
- ################# MARKDOWN CONTROLLS #################
- pannel.pack_start(Gtk.VSeparator(), False, False, 10)
- def do_mark(w, r, l):
- tb = view.get_buffer()
- s, e = tb.get_selection_bounds()
- tb.insert(s, r)
- s, e = tb.get_selection_bounds()
- tb.insert(e, l)
-
- print(r, l)
-
- bold = Gtk.Button()
- bold.connect("clicked", do_mark, "**", "**")
- bold.add(ui.icon(win, "format-text-bold"))
- bold.set_relief(Gtk.ReliefStyle.NONE)
- pannel.pack_start(bold, False, False, False)
- italic = Gtk.Button()
- italic.connect("clicked", do_mark, "*", "*")
- italic.add(ui.icon(win, "format-text-italic"))
- italic.set_relief(Gtk.ReliefStyle.NONE)
- pannel.pack_start(italic, False, False, False)
- code = Gtk.Button("</>")
- code.connect("clicked", do_mark, "`", "`")
- code.set_relief(Gtk.ReliefStyle.NONE)
- pannel.pack_start(code, False, False, False)
- pannel.pack_start(Gtk.VSeparator(), False, False, 10)
- #################### PROMOTE BUTTON ######################
- pannel.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
- pannel.pack_start(Gtk.Label(" Promote FastLBRY: "), False, False, 0)
- switch = Gtk.Switch()
- switch.set_tooltip_text("Adds a little link to FastLBRY visible in all other LBRY apps.")
- pannel.pack_start(switch, False, False, 0)
- switch.set_active(win.settings["promote_fast_lbry_in_comments"])
-
- def on_promote(w, e):
- win.settings["promote_fast_lbry_in_comments"] = switch.get_active()
- settings.save(win.settings)
-
- switch.connect("notify::active", on_promote)
-
- pannel.pack_start(Gtk.VSeparator(), False, False, 10)
-
-
- else:
- vbox.pack_start(Gtk.Label("To comment, Make a channel"), False, False, 30)
-
- return vbox
- def send_comment(win, message, claim_id):
- # if the user wants to promote FastLBRY
- if win.settings["promote_fast_lbry_in_comments"]:
- message = message + BUTTON_GTK_PROMOTE # See the beginning of the file
-
- # claim_id = win.resolved["claim_id"]
- channel_name = win.channel["name"]
- channel_id = win.channel["claim_id"]
- sigs = sign(message, channel_name)
- if not sigs:
- return
-
- params = {
- "channel_id": channel_id,
- "channel_name": channel_name,
- "claim_id": claim_id,
- "comment": message,
- **sigs
- }
- if win.commenting[claim_id]["reply"]["to"]:
- params["parent_id"] = win.commenting[claim_id]["reply"]["to"]
- # Make sure to clean that up
- for ch in win.commenting[claim_id]["reply"]["box"].get_children():
- ch.destroy()
- win.commenting[claim_id]["reply"]["to"] = ""
-
- out = comment_request("comment.Create", params)
- i = out["result"]
- # RENDERING THE NEWLY DONW COMMENT INTO THE PAGE
- # TODO: It duplicates it when the comment is actually loaded
- win.commenting[claim_id]["data"]["result"]["items"].append(i)
- print(i["comment_id"])
- box = win.commenting[claim_id]["box"]
- def render(win, box, i):
- render_single_comment(win, box, i)
- box.show_all()
- GLib.idle_add(render, win, box, i)
- def sign(data: str = "", channel: str = "", message: str = "Channel to sign data with:", hexdata: str = ""):
- """
- Sign a string or hexdata and return the signatures
- Keyword arguments:
- data -- a string to sign
- channel -- channel name to sign with (e.g. "@example"). Will prompt for one if not given.
- message -- message to give when selecting a channel. Please pass this if not passing channel.
- hexdata -- direct hexadecimal data to sign
- """
- if (not data and not hexdata) or (data and hexdata):
- raise ValueError("Must give either data or hexdata")
- elif data:
- hexdata = data.encode().hex()
- if not channel:
- channel = select(message)
- if not channel.startswith("@"):
- channel = "@" + channel
- try:
- sigs = fetch.lbrynet("channel_sign", {"channel_name":channel, "hexdata":hexdata})
-
- # sigs = check_output([flbry_globals["lbrynet"],
- # "channel", "sign",
- # "--channel_name=" + channel,
- # "--hexdata=" + hexdata])
- # sigs = json.loads(sigs)
- print(sigs)
-
- return sigs
- except:
- print("Stupid Error")
- return
|