cli.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #!/usr/bin/env python3
  2. import os
  3. import os.path
  4. import sys
  5. from pprint import pprint
  6. import requests
  7. import argparse
  8. from rscli import rsfiles
  9. from rscli.httputils import req
  10. try:
  11. from colors import color
  12. has_colors = True
  13. except ImportError:
  14. has_colors = False
  15. if not has_colors or not sys.stdout.isatty():
  16. def color(text, *args, **kwargs):
  17. return text
  18. def err(msg):
  19. print(color(msg, fg="red", style="bold"))
  20. def is_group_subscribed(mSubscribeFlags):
  21. return bool(mSubscribeFlags & 4)
  22. def main_forum_list(args):
  23. r = req(args, "/rsGxsForums/getForumsSummaries")
  24. forums = r.json()["forums"]
  25. for item in forums:
  26. if is_group_subscribed(item["mSubscribeFlags"]):
  27. if "notsubscribed" in args.select:
  28. continue
  29. style = "bold"
  30. else:
  31. if "subscribed" in args.select:
  32. continue
  33. style = None
  34. print(color(item["mGroupName"], style=style, fg="green"))
  35. print(" " + color(item["mGroupId"], style="underline"))
  36. def main_forum_read(args):
  37. r = req(args, "/rsGxsForums/getForumMsgMetaData", {"forumId": args.forum_id})
  38. items = r.json()["msgMetas"]
  39. items.sort(key=lambda p: p["mPublishTs"], reverse=True)
  40. if args.long:
  41. msgs = [item["mMsgId"] for item in items[: args.num_posts]]
  42. items_r = req(
  43. args,
  44. "/rsGxsForums/getForumContent",
  45. {"forumId": args.forum_id, "msgsIds": msgs},
  46. )
  47. items = items_r.json()["msgs"]
  48. items.sort(key=lambda p: p["mMeta"]["mPublishTs"], reverse=True)
  49. for item in items:
  50. print(color(item["mMeta"]["mMsgName"], style="bold", fg="green"))
  51. print()
  52. print(item["mMsg"]) # TODO: html2txt
  53. print()
  54. else:
  55. for item in items[: args.num_posts]:
  56. print(color(item["mMsgName"], style="bold", fg="green"))
  57. print(" " + color(item["mMsgId"], style="underline"))
  58. def main_channel_list(args):
  59. r = req(args, "/rsGxsChannels/getChannelsSummaries")
  60. channels = r.json()["channels"]
  61. for item in channels:
  62. if is_group_subscribed(item["mSubscribeFlags"]):
  63. if "notsubscribed" in args.select:
  64. continue
  65. style = "bold"
  66. else:
  67. if "subscribed" in args.select:
  68. continue
  69. style = None
  70. print(color(item["mGroupName"], style=style, fg="green"))
  71. print(" " + color(item["mGroupId"], style="underline"))
  72. def main_channel_read(args):
  73. r = req(args, "/rsGxsChannels/getContentSummaries", {"channelId": args.channel_id})
  74. posts = r.json()["summaries"]
  75. posts.sort(key=lambda p: p["mPublishTs"], reverse=True)
  76. if args.long:
  77. msgs = [post["mMsgId"] for post in posts[: args.num_posts]]
  78. posts_r = req(
  79. args,
  80. "/rsGxsChannels/getChannelContent",
  81. {"channelId": args.channel_id, "contentsIds": msgs},
  82. )
  83. posts = posts_r.json()["posts"]
  84. posts.sort(key=lambda p: p["mMeta"]["mPublishTs"], reverse=True)
  85. for post in posts:
  86. print(color(post["mMeta"]["mMsgName"], style="bold", fg="green"))
  87. print()
  88. print(post["mMsg"])
  89. print()
  90. else:
  91. for post in posts[: args.num_posts]:
  92. print(color(post["mMsgName"], style="bold", fg="green"))
  93. print(" " + color(post["mMsgId"], style="underline"))
  94. def main_channel_show(args):
  95. r = req(args, "/rsGxsChannels/getChannelsInfo", {"chanIds": [args.channel_id]})
  96. data = r.json()
  97. channels = data["channelsInfo"]
  98. for chan in channels:
  99. print(color(chan["mMeta"]["mGroupName"], style="bold", fg="green"))
  100. print(" " + color(chan["mMeta"]["mGroupId"], style="underline"))
  101. print(" " + chan["mDescription"])
  102. print(color("Last Post:", style="bold") + " \t%s" % chan["mMeta"]["mLastPost"])
  103. def main_channel_post_v1(args):
  104. r = req(
  105. args,
  106. "/rsGxsChannels/createPost",
  107. {
  108. "post": {
  109. "mMeta": {"mGroupId": args.channel_id, "mMsgName": args.post_title},
  110. "mMsg": args.post_body,
  111. }
  112. },
  113. )
  114. if r.status_code != 200:
  115. print(color("ERROR: could not create post", fg="red", style="bold"))
  116. print("Error %d" % r.status_code)
  117. sys.exit(1)
  118. ret = r.json()
  119. if ret.get("retval", True) is False:
  120. print(color("ERROR: could not create post", fg="red", style="bold"))
  121. pprint(ret)
  122. sys.exit(1)
  123. pprint(ret)
  124. def main_channel_post(args):
  125. attachments = [
  126. {
  127. "mHash": digest,
  128. "mName": os.path.basename(fpath),
  129. "mSize": os.stat(fpath).st_size,
  130. }
  131. for digest, fpath in zip(
  132. rsfiles.file_publish(args, args.attach_fpaths), args.attach_fpaths
  133. )
  134. ]
  135. try:
  136. r = req(
  137. args,
  138. "/rsGxsChannels/createPostV2",
  139. {
  140. "channelId": args.channel_id,
  141. "title": args.post_title,
  142. "mBody": args.post_body,
  143. "files": attachments,
  144. },
  145. )
  146. except requests.exceptions.HTTPError as exc:
  147. if exc.response.status_code != 404:
  148. raise
  149. else:
  150. ret = r.json()
  151. if ret.get("retval", True) is False:
  152. print(color("ERROR: could not create post", fg="red", style="bold"))
  153. print(ret["errorMessage"])
  154. pprint(ret)
  155. sys.exit(1)
  156. print(color(ret["postId"], fg="green", style="bold"))
  157. return
  158. return main_channel_post_v1(args)
  159. def main_file_publish(args):
  160. ret = rsfiles.file_publish(args, args.fnames)
  161. for filehash, fname in zip(ret, args.fnames):
  162. print(color(filehash, fg="green") + " \t%s" % fname)
  163. print(" " + rsfiles.get_file_link(args, filehash, fname=fname))
  164. def get_parser():
  165. p = argparse.ArgumentParser()
  166. p.add_argument("--endpoint", default="http://127.0.0.1:9092")
  167. p.add_argument("-u", "--auth", dest="auth")
  168. p_sub = p.add_subparsers()
  169. ch = p_sub.add_parser("channel")
  170. ch.add_argument("--channel-id")
  171. ch_sub = ch.add_subparsers()
  172. ch_list = ch_sub.add_parser("list")
  173. ch_list.add_argument(
  174. "--select",
  175. nargs="+",
  176. choices=["all", "subscribed", "notsubscribed"],
  177. default=["all"],
  178. )
  179. ch_list.set_defaults(mainfunc=main_channel_list)
  180. ch_show = ch_sub.add_parser("show")
  181. ch_show.set_defaults(mainfunc=main_channel_show)
  182. ch_read = ch_sub.add_parser("read")
  183. ch_read.add_argument("--long", action="store_true", default=False)
  184. ch_read.add_argument("--num-posts", type=int, default=10)
  185. ch_read.set_defaults(mainfunc=main_channel_read)
  186. ch_post = ch_sub.add_parser("post")
  187. ch_post.set_defaults(mainfunc=main_channel_post)
  188. ch_post.add_argument("--post-title")
  189. ch_post.add_argument("--post-body")
  190. ch_post.add_argument("--attach-name", nargs="*", dest="attach_fpaths")
  191. forum = p_sub.add_parser("forum")
  192. forum.add_argument("--forum-id")
  193. forum_sub = forum.add_subparsers()
  194. forum_list = forum_sub.add_parser("list")
  195. forum_list.add_argument(
  196. "--select",
  197. nargs="+",
  198. choices=["all", "subscribed", "notsubscribed"],
  199. default=["all"],
  200. )
  201. forum_list.set_defaults(mainfunc=main_forum_list)
  202. forum_read = forum_sub.add_parser("read")
  203. forum_read.add_argument("--long", action="store_true", default=False)
  204. forum_read.add_argument("--num-posts", type=int, default=10)
  205. forum_read.set_defaults(mainfunc=main_forum_read)
  206. files = p_sub.add_parser("file")
  207. files_sub = files.add_subparsers()
  208. files_list = files_sub.add_parser("publish")
  209. files_list.add_argument("fnames", nargs="+", metavar="fname")
  210. files_list.set_defaults(mainfunc=main_file_publish)
  211. # TODO: channel rss -> read and convert to rss
  212. return p
  213. def main():
  214. p = get_parser()
  215. args = p.parse_args()
  216. if getattr(args, "mainfunc", None) is None:
  217. print("Not a complete command")
  218. sys.exit(2)
  219. args.mainfunc(args)
  220. if __name__ == "__main__":
  221. main()