cli.py 7.6 KB

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