channel.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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 perform a simple search on the LBRY network.
  30. from subprocess import *
  31. import json
  32. from flbry import url
  33. from flbry import following
  34. from flbry import wallet
  35. from flbry import markdown
  36. from flbry import publish
  37. from flbry.variables import *
  38. def simple(args=""):
  39. # The user might write the search argument right in the same
  40. # line as the work search.
  41. #
  42. # : channel blenderdumbass
  43. #
  44. # Or they can type nothing. And be confused of what happened.
  45. # So I want to provide a catcher here. If they type nothing it
  46. # will ask them to provide a search query.
  47. if not args:
  48. args = input(" Channel url :: ")
  49. if not args.startswith("@") and not args.startswith("lbry://@"):
  50. args = "@"+args
  51. # So we want to request a query to the SDK to search what ever
  52. # the user wants. The problem is it can be a very large output.
  53. # For example the "blender dumbass" query returns 1000 claims
  54. # on the LBRY network. And people will wait for a very long time
  55. # on something that might have a million claims.
  56. # So instead we are going to request only the first 20 and let
  57. # the user load more.
  58. w, h = tsize()
  59. page_size = h - 5
  60. page = 1
  61. while True:
  62. # Printing the search query and page number
  63. center("CHANNEL: "+args+" PAGE:"+str(page))
  64. out = check_output(["flbry/lbrynet",
  65. "claim", "search", '--channel='+args,
  66. '--page='+str(page),
  67. '--page_size='+str(page_size),
  68. "--no_totals",
  69. '--order_by=release_time'])
  70. # Now we want to parse the json
  71. try:
  72. out = json.loads(out)
  73. except:
  74. print(" Connect to LBRY first.")
  75. return
  76. try:
  77. data_print = {"categories":["Type", "Title"],
  78. "size":[1,5],
  79. "data":[]}
  80. # List what we found
  81. for n, i in enumerate(out["items"]):
  82. title = "---!Failed Loading Title---"
  83. ftype = "claim"
  84. try:
  85. try:
  86. title = i["value"]["title"]
  87. except:
  88. title = i['name']
  89. try:
  90. ftype = what[i["value"]["stream_type"]]
  91. except:
  92. ftype = what[i["value_type"]]
  93. except:
  94. pass
  95. data_print["data"].append([ftype, title])
  96. table(data_print)
  97. # Tell the user that he might want to load more
  98. center("---type 'more' to load more---")
  99. page = page +1
  100. # Error messages
  101. except Exception as e:
  102. if "code" in out:
  103. print(" Error code: ", out["code"] )
  104. if out["code"] == -32500:
  105. print(" SDK is still starting. Patience!")
  106. else:
  107. print(" Error :", e)
  108. return
  109. channel_commands = [
  110. "rss",
  111. "follow",
  112. "unfollow",
  113. "more",
  114. "support",
  115. "tip"
  116. ]
  117. complete(channel_commands)
  118. # Making sure that we stop every time a new page is reached
  119. while True:
  120. c = input(typing_dots())
  121. if c == "rss":
  122. rss = out["items"][0]["signing_channel"]["short_url"]
  123. rss = rss.replace("#", ":")
  124. rss = rss.split("lbry://", 1)[1]
  125. print(" https://odysee.com/$/rss/"+rss)
  126. elif c == "follow":
  127. channel = out["items"][0]["signing_channel"]["permanent_url"]
  128. try:
  129. name = out["items"][0]["signing_channel"]["value"]["title"]
  130. except:
  131. name = out["items"][0]["signing_channel"]["normalized_name"]
  132. following.follow_channel(channel, name)
  133. elif c == "unfollow":
  134. channel = out["items"][0]["signing_channel"]["permanent_url"]
  135. try:
  136. name = out["items"][0]["signing_channel"]["value"]["title"]
  137. except:
  138. name = out["items"][0]["signing_channel"]["normalized_name"]
  139. following.unfollow_channel(channel, name)
  140. elif c == "support":
  141. wallet.support(out["items"][0]["signing_channel"]["claim_id"])
  142. elif c == "tip":
  143. wallet.support(out["items"][0]["signing_channel"]["claim_id"], True)
  144. else:
  145. break
  146. complete(channel_commands)
  147. if c != "more":
  148. break
  149. try:
  150. c = int(c)
  151. except:
  152. return
  153. while True:
  154. url.get(out["items"][c]["canonical_url"])
  155. c = input(typing_dots())
  156. if not c:
  157. break
  158. try:
  159. c = int(c)
  160. except:
  161. return
  162. def select(message="", claim_id=False, anonymous=False):
  163. # This fucntion will give users to select one of their channels.
  164. center(message)
  165. out = check_output(["flbry/lbrynet",
  166. "channel", "list"])
  167. # Now we want to parse the json
  168. try:
  169. out = json.loads(out)
  170. except:
  171. print(" Connect to LBRY first.")
  172. return
  173. d = {"categories":["lbry url", "title"],
  174. "size":[1,2],
  175. "data":[]}
  176. for n, i in enumerate(out["items"]):
  177. name = "[no name]"
  178. title = "[no title]"
  179. try:
  180. name = i["name"]
  181. title = i["value"]["title"]
  182. except:
  183. pass
  184. d["data"].append([name, title])
  185. if anonymous:
  186. d["data"].append(["[anonymous]", "[no title]"])
  187. table(d)
  188. center("select a channel by typing it's number")
  189. select = input(typing_dots())
  190. try:
  191. select = int(select)
  192. if select > len(out["items"])-1 and anonymous:
  193. if claim_id:
  194. return None, None
  195. return None
  196. if claim_id:
  197. return out["items"][select]["name"], out["items"][select]["claim_id"]
  198. return out["items"][select]["name"]
  199. except:
  200. raise()
  201. if claim_id:
  202. return out["items"][0]["name"], out["items"][0]["claim_id"]
  203. return out["items"][0]["name"]
  204. def create():
  205. # The dictionaries for the data table
  206. d = {"categories": ["Name", "Bid", "Title", "Description"],
  207. "size": [2,1,3,6],
  208. "data": []}
  209. d2 = {"categories": ["Email", "Website URL"],
  210. "size": [1,1],
  211. "data": []}
  212. d3 = {"categories": ["Thumbnail URL", "Cover URL"],
  213. "size": [1,1],
  214. "data": []}
  215. d_tags = {"categories": [],
  216. "size": [],
  217. "data": [[]]}
  218. d_langs = {"categories": [],
  219. "size": [],
  220. "data": [[]]}
  221. # Put some default values so the table looks nice
  222. # They have their own variables so we can check against them later
  223. bid = 0.0001
  224. default_title = "[no title]"
  225. default_description = "[no description]"
  226. default_email = "[no email]"
  227. default_web_url = "[no website]"
  228. default_thumb_url = "[no thumbnail]"
  229. default_cover_url = "[no cover image]"
  230. default_tags = ["[no tags]"]
  231. default_langs = ["[no languages]"]
  232. title = default_title
  233. description = default_description
  234. email = default_email
  235. web_url = default_web_url
  236. thumb_url = default_thumb_url
  237. cover_url = default_cover_url
  238. tags = default_tags
  239. langs = default_langs
  240. name = input(" Name: ")
  241. if not name.startswith("@"):
  242. name = "@" + name
  243. complete([
  244. "name",
  245. "bid",
  246. "title",
  247. "description",
  248. "email",
  249. "website",
  250. "thumbnail",
  251. "cover",
  252. "tags",
  253. "languages",
  254. "help",
  255. "create"
  256. ])
  257. while True:
  258. # Just setting the "data" list wasn't working, so clear it then append to it
  259. d["data"] = []
  260. d2["data"] = []
  261. d3["data"] = []
  262. d["data"].append([name, str(bid), title, description])
  263. d2["data"].append([email, web_url])
  264. d3["data"].append([thumb_url, cover_url])
  265. d_tags["categories"] = []
  266. d_tags["size"] = []
  267. d_tags["data"] = [[]]
  268. for tag in tags:
  269. d_tags["categories"].append(" ")
  270. d_tags["size"].append(1)
  271. d_tags["data"][0].append(tag)
  272. d_langs["categories"] = []
  273. d_langs["size"] = []
  274. d_langs["data"] = [[]]
  275. for lang in langs:
  276. d_langs["categories"].append(" ")
  277. d_langs["size"].append(1)
  278. d_langs["data"][0].append(lang)
  279. table(d, False)
  280. table(d2, False)
  281. table(d3, False)
  282. table(d_tags, False)
  283. table(d_langs, False)
  284. center("--- for commands type 'help' ---")
  285. c = input(typing_dots())
  286. if not c:
  287. return
  288. if c == "name":
  289. name = input(" Name: ")
  290. if not name.startswith("@"):
  291. name = "@" + name
  292. elif c == "bid":
  293. while True:
  294. bid = input(" Bid: ")
  295. try:
  296. float(bid)
  297. break
  298. except:
  299. center("Bid is not a number, try again", "bdrd")
  300. bid = ""
  301. elif c == "title":
  302. title = input(" Title: ")
  303. elif c.startswith("description"):
  304. c = c + ' '
  305. a = c[c.find(" "):]
  306. if len(a) > 1:
  307. description = file_or_editor(a, "Type the description here. Don't forget to save. Then return to FastLBRY.")
  308. else:
  309. description = input(" Description: ")
  310. elif c == "email":
  311. email = input(" Email: ")
  312. elif c == "website":
  313. web_url = input(" Website URL: ")
  314. elif c == "thumbnail":
  315. thumb_url = input(" Thumbnail URL: ")
  316. # Try to upload
  317. thumb_url = publish.speech_upload(thumb_url)
  318. elif c == "cover":
  319. cover_url = input(" Cover URL: ")
  320. # Try to upload
  321. cover_url = publish.speech_upload(cover_url)
  322. elif c == "tags":
  323. tags = input(" Enter the tags for the channel, separated by commas: ")
  324. tags = tags.split(",")
  325. for tag in tags:
  326. tag.strip()
  327. elif c == "languages":
  328. langs = input(" Enter the languages for the channel, separated by commas: ")
  329. langs = langs.split(",")
  330. for lang in langs:
  331. lang.strip()
  332. elif c == "help":
  333. markdown.draw("help/create-channel.md", "Create Channel Help")
  334. elif c == "create":
  335. command = ["flbry/lbrynet", "channel", "create", "--name="+name, "--bid="+str(bid)]
  336. if title != default_title:
  337. command.append("--title="+title)
  338. if description != default_description:
  339. command.append("--description="+description)
  340. if email != default_email:
  341. command.append("--email="+email)
  342. if web_url != default_web_url:
  343. command.append("--website_url="+web_url)
  344. if thumb_url != default_thumb_url:
  345. command.append("--thumbnail_url="+thumb_url)
  346. if cover_url != default_cover_url:
  347. command.append("--cover_url="+cover_url)
  348. if tags != default_tags:
  349. for tag in tags:
  350. command.append("--tags="+tag)
  351. if langs != default_langs:
  352. for lang in langs:
  353. command.append("--languages="+lang)
  354. out = check_output(command)
  355. out = json.loads(out)
  356. if "message" in out:
  357. center("Error creating channel: "+out["message"], "bdrd")
  358. else:
  359. center("Successfully created "+name, "bdgr")
  360. return