publish.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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 publish a selected file into LBRY Network.
  30. from subprocess import *
  31. import json
  32. import os
  33. import random
  34. from flbry import url
  35. from flbry import channel
  36. from flbry import markdown
  37. from flbry.variables import *
  38. from flbry import settings
  39. def upload(data):
  40. # This function actually will upload the file.
  41. # reference:
  42. # --name | lbry:// url to publish to
  43. # --bid | LBC to use while publishing
  44. # --fee_amount | How much does one need to pay for the publication
  45. # --file_path | The path to a file that's going to be uploaded
  46. # --title | Title of the publication on the LBRY network
  47. # --license | License of the publication
  48. # --license_url | Link to the license
  49. # --thumbnail_url | Link to a thumbnail image
  50. # --description | A string of text describing the publication
  51. # --tags | List of tags.
  52. # --channel_name | Name of a channel to which to upload
  53. # ( without it will be anonymous)
  54. # More commands to upload function you can see at:
  55. # https://lbry.tech/api/sdk#publish
  56. # An example of a working publish command:
  57. # ./lbrynet publish --name="testing_upload_via_sdk_v2" --bid=0.01
  58. # --file_path="/home/vcs/Desktop/upload_test_file.md"
  59. # --title="Testing Uploading Directly from the LBRY SDK v2"
  60. # --license="CC-BY-SA" --channel_name="@blenderdumbass"
  61. p = ["flbry/lbrynet", "publish", "--name="+data["name"],
  62. "--bid="+str(data["bid"]), "--file_path="+data["file_path"]]
  63. for i in ["title", "license", "license_url", "thumbnail_url", "description", "channel_name", "fee_amount"]:
  64. if i in data:
  65. if data[i]:
  66. p.append("--"+i+"="+str(data[i]))
  67. if data["fee_amount"]:
  68. p.append("--fee_currency=LBC")
  69. if "tags" in data:
  70. if data["tags"]:
  71. for i in data["tags"]:
  72. p.append("--tags="+i) # THIS IS STUPID IK. BUT IT WORKS
  73. out = check_output(p)
  74. try:
  75. out = json.loads(out)
  76. except:
  77. print(" Connect to LBRY first.")
  78. return
  79. return out
  80. def view_data(data):
  81. # this function will print the data
  82. # LBRY URL
  83. d = {"categories": ["LBRY URL"],
  84. "size":[1],
  85. "data":[["lbry://"+data["name"]]]}
  86. table(d, False)
  87. # FILE PATH
  88. d = {"categories": ["File Path"],
  89. "size":[1],
  90. "data":[[data["file_path"]]]}
  91. table(d, False)
  92. # CHANNEL, BID AND PRICE
  93. if not data["channel_name"]:
  94. channel = "[anonymous]"
  95. else:
  96. channel = data["channel_name"]
  97. if not data["fee_amount"]:
  98. price = "Gratis"
  99. else:
  100. price = str(data["fee_amount"])+" LBC"
  101. d = {"categories": ["Channel ID", "LBC BID", "Price"],
  102. "size":[1, 1, 1],
  103. "data":[[channel, str(data["bid"])+" LBC", price]]}
  104. table(d, False)
  105. # TITLE AND THUMBNAIL
  106. if not data["thumbnail_url"]:
  107. thumb = "[no thumbnail]"
  108. else:
  109. thumb = data["thumbnail_url"]
  110. if not data["title"]:
  111. title = "[no title]"
  112. else:
  113. title = data["title"]
  114. d = {"categories": ["Thumbnail", "Title"],
  115. "size":[2, 3],
  116. "data":[[thumb, title]]}
  117. table(d, False)
  118. # LICENSING INFORMATION
  119. if not data["license"]:
  120. license = "[no license]"
  121. else:
  122. license = data["license"]
  123. if not data["license_url"]:
  124. lurl = "[no license url]"
  125. else:
  126. lurl = data["license_url"]
  127. d = {"categories": ["License", "URL"],
  128. "size":[3, 2],
  129. "data":[[license, lurl]]}
  130. table(d, False)
  131. # DESCRIPTION PREVIEW
  132. d = {"categories": ["DESCRIPTION PREVIEW"],
  133. "size":[1],
  134. "data":[[data["description"].replace("\n", " ")]]}
  135. table(d, False)
  136. # Tags PREVIEW
  137. d = {"categories": ["TAGS"],
  138. "size":[1],
  139. "data":[[data["tags"]]]}
  140. table(d, False)
  141. def configure(file_path=""):
  142. # This function will prepare the publication data, before sending it
  143. # to the upload() function above.
  144. file_path = os.path.expanduser(file_path)
  145. while not os.path.exists(file_path):
  146. center("File '"+file_path+"' not found", "bdrd")
  147. file_path = input(" File path:")
  148. file_path = os.path.expanduser(file_path)
  149. lbryname = ""
  150. good = "qwertyuiopasdfghjklzxcvbnm-_QWERTYUIOPASDFGHJKLZXCVBNM1234567890"
  151. for i in range(70):
  152. lbryname = lbryname + random.choice(good)
  153. center("Upload Manager of FastLBRY")
  154. data = {"name":lbryname,
  155. "bid":0.001,
  156. "file_path":file_path,
  157. "title":"",
  158. "license":"",
  159. "license_url":"",
  160. "thumbnail_url":"",
  161. "channel_id":"",
  162. "channel_name":"",
  163. "description":"",
  164. "fee_amount":0,
  165. "tags":[]
  166. }
  167. # Completer thingy
  168. complete([
  169. "file",
  170. "bid",
  171. "price",
  172. "url",
  173. "title",
  174. "license",
  175. "channel",
  176. "tags",
  177. "description",
  178. "help",
  179. "save",
  180. "load",
  181. "publish",
  182. "thumbnail"
  183. ])
  184. while True:
  185. # preview the data
  186. view_data(data)
  187. center("---type 'help' to read how it works---")
  188. # input
  189. c = input(typing_dots())
  190. if not c:
  191. break
  192. # Update file_path
  193. elif c.startswith("file"):
  194. if " " in c:
  195. file_path = c[c.find(" ")+1:]
  196. else:
  197. file_path = input(" File path:")
  198. while not os.path.exists(file_path):
  199. center("File '"+file_path+"' not found", "bdrd")
  200. file_path = input(" File path:")
  201. data["file_path"] = file_path
  202. # Update the bid info
  203. elif c.startswith("bid"):
  204. if " " in c:
  205. bid = c[c.find(" ")+1:]
  206. else:
  207. bid = input(" Bid: ")
  208. while True:
  209. try:
  210. bid = float(bid)
  211. if not bid > 0.0001:
  212. 1 / 0 # Fail switch
  213. break
  214. except:
  215. center("Bid cannot be: "+str(bid), "bdrd")
  216. bid = input(" Bid: ")
  217. data["bid"] = bid
  218. # Setup a price
  219. elif c.startswith("price"):
  220. if " " in c:
  221. price = c[c.find(" ")+1:]
  222. else:
  223. price = input(" Price: ")
  224. while True:
  225. try:
  226. price = float(price)
  227. if price < 0:
  228. 1 / 0 # Fail switch
  229. break
  230. except:
  231. center("Price cannot be: "+str(price), "bdrd")
  232. price = input(" Price: ")
  233. data["fee_amount"] = price
  234. # URL for the publication
  235. elif c.startswith("url"):
  236. if " " in c:
  237. url = c[c.find(" ")+1:]
  238. else:
  239. url = input(" LBRY URL : lbry://")
  240. name = ""
  241. for i in url:
  242. if i in good:
  243. name = name + i
  244. else:
  245. name = name + "-"
  246. data["name"] = name
  247. # Title
  248. elif c.startswith("title"):
  249. if " " in c:
  250. title = c[c.find(" ")+1:]
  251. else:
  252. title = input(" Title: ")
  253. data["title"] = title
  254. # License setting
  255. elif c == "license":
  256. lsnzs = []
  257. for i in licenses:
  258. lsnzs.append([i[0],i[2]])
  259. d = {"categories":["Name","Comment"],
  260. "size":[1,1],
  261. "data":lsnzs}
  262. table(d)
  263. center("---choose a license or press enter for custom---")
  264. lc = input(typing_dots())
  265. try:
  266. lselect = licenses[int(lc)]
  267. lname = lselect[0]
  268. llink = lselect[1]
  269. except:
  270. lname = input(" License name: ")
  271. llink = input(" License link: ")
  272. data["license"] = lname
  273. data["license_url"] = llink
  274. # Channel
  275. elif c == "channel":
  276. ch, chid = channel.select("Select from where to publish.", claim_id=True)
  277. data["channel_id"] = chid
  278. data["channel_name"] = ch
  279. # Tags
  280. elif c.startswith("tags"):
  281. if " " in c:
  282. th = c[c.find(" ")+1:]
  283. else:
  284. th = input(" Tags (separated by,): ")
  285. data["tags"] = th.split(",")
  286. elif c.startswith("thumbnail"):
  287. if " " in c:
  288. th = c[c.find(" ")+1:]
  289. else:
  290. th = input(" Thumbnail url: ")
  291. # Try to upload thumbnail
  292. data["thumbnail_url"] = speech_upload(th)
  293. # Description
  294. elif c.startswith("description"):
  295. if " " in c:
  296. df = c[c.find(" ")+1:]
  297. try:
  298. text = open(df, "r")
  299. text = text.read()
  300. except:
  301. text = open("/tmp/fastlbrydescriptiontwriter.txt", "w")
  302. text.write("Type your description here. Don't forget to save. Then return to FastLBRY.")
  303. text.close()
  304. os.system(df+" /tmp/fastlbrydescriptiontwriter.txt")
  305. center("Press Enter when the file is ready and saved.")
  306. input()
  307. text = open("/tmp/fastlbrydescriptiontwriter.txt", "r")
  308. text = text.read()
  309. else:
  310. text = input(" Description: ")
  311. data["description"] = text
  312. elif c == "help":
  313. markdown.draw("help/publish.md", "Publishing Help")
  314. # SAVE / LOAD OPTIONS
  315. elif c.startswith("save"):
  316. if " " in c:
  317. pn = c[c.find(" ")+1:]
  318. else:
  319. pn = input(" Preset Name: ")
  320. # Create the preset folder is it's not there
  321. try:
  322. os.mkdir(settings.get_settings_folder()+"presets")
  323. except:
  324. pass
  325. # Write the json file
  326. with open(settings.get_settings_folder()+"presets/"+pn+'.json', 'w') as f:
  327. json.dump(data, f, indent=4, sort_keys=True)
  328. elif c.startswith("load"):
  329. if " " in c:
  330. pn = c[c.find(" ")+1:]
  331. else:
  332. pn = input(" Preset Name: ")
  333. # loading the json file
  334. try:
  335. name = data["name"]
  336. file_path = data["file_path"]
  337. with open(settings.get_settings_folder()+"presets/"+pn+'.json') as f:
  338. data = json.load(f)
  339. data["file_path"] = file_path
  340. data["name"] = name
  341. except:
  342. center("There is no '"+pn+"' preset!", "bdrd")
  343. # PUBLISHING
  344. elif c == "publish":
  345. out = upload(data)
  346. try:
  347. center("LBRY URL FULL TEXT:")
  348. print(out['outputs'][0]['permanent_url'])
  349. center("HTTPS URL FULL TEXT:")
  350. print(out['outputs'][0]['permanent_url'].replace("lbry://","https://spee.ch/"))
  351. center("Publishing is done successfully!", "bdgr")
  352. center("Confirming publication... It may take a few minutes.")
  353. except:
  354. center("Failed", "bdrd")
  355. center("================= ERROR! ================", "bdrd")
  356. try:
  357. for line in out["message"].split("\n"):
  358. center(line, "bdrd")
  359. except:
  360. print(out)
  361. center("=========================================", "bdrd")
  362. return
  363. def speech_upload(file):
  364. file = os.path.expanduser(file)
  365. if os.path.isfile(file):
  366. center("Uploading file to LBRY")
  367. rndname = ""
  368. good = "qwertyuiopasdfghjklzxcvbnm-_QWERTYUIOPASDFGHJKLZXCVBNM1234567890"
  369. for i in range(70):
  370. rndname = rndname + random.choice(good)
  371. try:
  372. out = upload({"name":rndname,
  373. "bid":0.001,
  374. "file_path":file,
  375. "title":"",
  376. "license":"",
  377. "license_url":"",
  378. "thumbnail_url":"",
  379. "channel_id":"",
  380. "channel_name":"",
  381. "description":"",
  382. "fee_amount":0,
  383. "tags":[]
  384. })
  385. return out['outputs'][0]['permanent_url'].replace("lbry://","https://spee.ch/")
  386. except:
  387. return ""
  388. center("Failed uploading file", "bdrd")
  389. else:
  390. return file