|
@@ -1,14 +1,11 @@
|
|
#!/usr/bin/env python3
|
|
#!/usr/bin/env python3
|
|
-import hashlib
|
|
|
|
import sys
|
|
import sys
|
|
-import time
|
|
|
|
-import uuid
|
|
|
|
from pprint import pprint
|
|
from pprint import pprint
|
|
import requests
|
|
import requests
|
|
import argparse
|
|
import argparse
|
|
-import os.path
|
|
|
|
|
|
|
|
-import retroshare
|
|
|
|
|
|
+from rscli import rsfiles
|
|
|
|
+from rscli.httputils import req
|
|
|
|
|
|
try:
|
|
try:
|
|
from colors import color
|
|
from colors import color
|
|
@@ -17,30 +14,16 @@ except ImportError:
|
|
def color(text, *args, **kwargs):
|
|
def color(text, *args, **kwargs):
|
|
return text
|
|
return text
|
|
|
|
|
|
-try:
|
|
|
|
- from fsdb import Fsdb
|
|
|
|
-except ImportError:
|
|
|
|
- Fsdb = None
|
|
|
|
|
|
|
|
|
|
|
|
def err(msg):
|
|
def err(msg):
|
|
- print(color(msg, fg='red', style='bold'))
|
|
|
|
|
|
+ print(color(msg, fg="red", style="bold"))
|
|
|
|
+
|
|
|
|
|
|
def is_group_subscribed(mSubscribeFlags):
|
|
def is_group_subscribed(mSubscribeFlags):
|
|
return bool(mSubscribeFlags & 4)
|
|
return bool(mSubscribeFlags & 4)
|
|
|
|
|
|
|
|
|
|
-def req(args, location, data=None):
|
|
|
|
- kwargs = {}
|
|
|
|
- if data is not None:
|
|
|
|
- kwargs["json"] = data
|
|
|
|
- r = requests.post(
|
|
|
|
- args.endpoint + location, auth=tuple(args.auth.split(":", 2)), **kwargs
|
|
|
|
- )
|
|
|
|
- r.raise_for_status()
|
|
|
|
- # TODO: handle r.status_code != 200
|
|
|
|
- return r
|
|
|
|
-
|
|
|
|
|
|
|
|
def main_forum_list(args):
|
|
def main_forum_list(args):
|
|
r = req(args, "/rsGxsForums/getForumsSummaries")
|
|
r = req(args, "/rsGxsForums/getForumsSummaries")
|
|
@@ -61,6 +44,7 @@ def main_forum_list(args):
|
|
def main_forum_read(args):
|
|
def main_forum_read(args):
|
|
r = req(args, "/rsGxsForums/getForumMsgMetaData", {"forumId": args.forum_id})
|
|
r = req(args, "/rsGxsForums/getForumMsgMetaData", {"forumId": args.forum_id})
|
|
items = r.json()["msgMetas"]
|
|
items = r.json()["msgMetas"]
|
|
|
|
+ items.sort(key=lambda p: p['mPublishTs'], reverse=True)
|
|
if args.long:
|
|
if args.long:
|
|
msgs = [item["mMsgId"] for item in items[: args.num_posts]]
|
|
msgs = [item["mMsgId"] for item in items[: args.num_posts]]
|
|
items_r = req(
|
|
items_r = req(
|
|
@@ -69,13 +53,14 @@ def main_forum_read(args):
|
|
{"forumId": args.forum_id, "msgsIds": msgs},
|
|
{"forumId": args.forum_id, "msgsIds": msgs},
|
|
)
|
|
)
|
|
items = items_r.json()["msgs"]
|
|
items = items_r.json()["msgs"]
|
|
|
|
+ items.sort(key=lambda p: p['mMeta']['mPublishTs'], reverse=True)
|
|
for item in items:
|
|
for item in items:
|
|
print(color(item["mMeta"]["mMsgName"], style="bold", fg="green"))
|
|
print(color(item["mMeta"]["mMsgName"], style="bold", fg="green"))
|
|
print()
|
|
print()
|
|
print(item["mMsg"]) # TODO: html2txt
|
|
print(item["mMsg"]) # TODO: html2txt
|
|
print()
|
|
print()
|
|
else:
|
|
else:
|
|
- for item in posts[: args.num_posts]:
|
|
|
|
|
|
+ for item in items[: args.num_posts]:
|
|
print(color(item["mMsgName"], style="bold", fg="green"))
|
|
print(color(item["mMsgName"], style="bold", fg="green"))
|
|
print(" " + color(item["mMsgId"], style="underline"))
|
|
print(" " + color(item["mMsgId"], style="underline"))
|
|
|
|
|
|
@@ -99,6 +84,7 @@ def main_channel_list(args):
|
|
def main_channel_read(args):
|
|
def main_channel_read(args):
|
|
r = req(args, "/rsGxsChannels/getContentSummaries", {"channelId": args.channel_id})
|
|
r = req(args, "/rsGxsChannels/getContentSummaries", {"channelId": args.channel_id})
|
|
posts = r.json()["summaries"]
|
|
posts = r.json()["summaries"]
|
|
|
|
+ posts.sort(key=lambda p: p['mPublishTs'], reverse=True)
|
|
if args.long:
|
|
if args.long:
|
|
msgs = [post["mMsgId"] for post in posts[: args.num_posts]]
|
|
msgs = [post["mMsgId"] for post in posts[: args.num_posts]]
|
|
posts_r = req(
|
|
posts_r = req(
|
|
@@ -107,6 +93,7 @@ def main_channel_read(args):
|
|
{"channelId": args.channel_id, "contentsIds": msgs},
|
|
{"channelId": args.channel_id, "contentsIds": msgs},
|
|
)
|
|
)
|
|
posts = posts_r.json()["posts"]
|
|
posts = posts_r.json()["posts"]
|
|
|
|
+ posts.sort(key=lambda p: p['mMeta']['mPublishTs'], reverse=True)
|
|
for post in posts:
|
|
for post in posts:
|
|
print(color(post["mMeta"]["mMsgName"], style="bold", fg="green"))
|
|
print(color(post["mMeta"]["mMsgName"], style="bold", fg="green"))
|
|
print()
|
|
print()
|
|
@@ -130,7 +117,6 @@ def main_channel_show(args):
|
|
|
|
|
|
|
|
|
|
def main_channel_post_v1(args):
|
|
def main_channel_post_v1(args):
|
|
- chid = args.channel_id
|
|
|
|
r = req(
|
|
r = req(
|
|
args,
|
|
args,
|
|
"/rsGxsChannels/createPost",
|
|
"/rsGxsChannels/createPost",
|
|
@@ -154,7 +140,6 @@ def main_channel_post_v1(args):
|
|
|
|
|
|
|
|
|
|
def main_channel_post(args):
|
|
def main_channel_post(args):
|
|
- chid = args.channel_id
|
|
|
|
try:
|
|
try:
|
|
r = req(
|
|
r = req(
|
|
args,
|
|
args,
|
|
@@ -179,89 +164,13 @@ def main_channel_post(args):
|
|
return main_channel_post_v1(args)
|
|
return main_channel_post_v1(args)
|
|
|
|
|
|
|
|
|
|
-def get_fsdb(args):
|
|
|
|
- if Fsdb is None:
|
|
|
|
- raise Exception('ERROR: library Fsdb is needed for file publishing')
|
|
|
|
- store_dir = os.path.expanduser('~/.config/rscli/store/default')
|
|
|
|
- return Fsdb(store_dir, fmode='660')
|
|
|
|
-
|
|
|
|
-def _file_publish(args, fnames):
|
|
|
|
- fsdb = get_fsdb(args)
|
|
|
|
- virtualname_path = os.path.join(fsdb.fsdbRoot, 'virtualname.txt')
|
|
|
|
- if os.path.exists(virtualname_path):
|
|
|
|
- virtualname = open(virtualname_path).read().strip()
|
|
|
|
- else:
|
|
|
|
- virtualname = 'rscli-%s' % uuid.uuid4()
|
|
|
|
- open(virtualname_path, 'w').write(virtualname)
|
|
|
|
- r = req(args, '/rsFiles/getSharedDirectories')
|
|
|
|
- if virtualname not in [shared['virtualname'] for shared in r.json()['dirs']]:
|
|
|
|
- r = req(args, '/rsFiles/addSharedDirectory', {'dir':{ 'filename': fsdb.fsdbRoot,
|
|
|
|
- 'virtualname': virtualname
|
|
|
|
- }})
|
|
|
|
- if not r.json()['retval']:
|
|
|
|
- raise Exception("Error: could not create shared dir for default store")
|
|
|
|
- r = req(args, '/rsFiles/getSharedDirectories')
|
|
|
|
- dir_filename = [d['filename']
|
|
|
|
- for d in r.json()['dirs']
|
|
|
|
- if d['virtualname'] == virtualname][0]
|
|
|
|
- r = req(args, '/rsFiles/requestDirDetails', { 'handle': 0 })
|
|
|
|
- children = [c for c in r.json()['details']['children']
|
|
|
|
- if c['name'] != '[Extra List]']
|
|
|
|
- for possibile_root in children:
|
|
|
|
- r = req(args, '/rsFiles/requestDirDetails',
|
|
|
|
- { 'handle': possibile_root['handle'] })
|
|
|
|
- found = [c for c in r.json()['details']['children']
|
|
|
|
- if c['name'] == dir_filename]
|
|
|
|
- if not found:
|
|
|
|
- raise Exception ('Error: could not find shared file in RS')
|
|
|
|
- handle = found[0]['handle']
|
|
|
|
-
|
|
|
|
- for fname in fnames:
|
|
|
|
- digest = fsdb.add(fname)
|
|
|
|
- # correct implementation: check hash inside storage
|
|
|
|
- # unfortunately it is very slow because we can't give
|
|
|
|
- # an hint to ForceDirectoryCheck for where to look
|
|
|
|
- # for new files
|
|
|
|
- # after the comment, there is a valid implementation, which has the defect
|
|
|
|
- # of being very coupled to retroshare implementation
|
|
|
|
- # r = req(args, '/rsFiles/ForceDirectoryCheck')
|
|
|
|
- #time.sleep(5)
|
|
|
|
- ## mo lo ricerchiamo va
|
|
|
|
- #looking_for = os.path.relpath(fsdb.get_file_path(digest),
|
|
|
|
- # fsdb.fsdbRoot).split(os.path.sep)
|
|
|
|
- #hashlib
|
|
|
|
- #for next_component in looking_for:
|
|
|
|
- # r = req(args, '/rsFiles/requestDirDetails', { 'handle': handle })
|
|
|
|
- # found = [c for c in r.json()['details']['children']
|
|
|
|
- # if c['name'] == next_component]
|
|
|
|
- # if not found:
|
|
|
|
- # raise Exception('Error: could not find shared file in RS')
|
|
|
|
- # handle = found[0]['handle']
|
|
|
|
- #r = req(args, '/rsFiles/requestDirDetails', { 'handle': handle })
|
|
|
|
- #filehash = r.json()['details']['hash']
|
|
|
|
- #yield filehash
|
|
|
|
-
|
|
|
|
- h = hashlib.new('sha1')
|
|
|
|
- h.update(open(fname, 'rb').read())
|
|
|
|
- yield h.hexdigest()
|
|
|
|
-
|
|
|
|
- r = req(args, '/rsFiles/ForceDirectoryCheck')
|
|
|
|
-
|
|
|
|
-def get_file_link(args, hash_digest, fname=None, size=None):
|
|
|
|
- fsdb = get_fsdb(args)
|
|
|
|
- if fname is None:
|
|
|
|
- # TODO: check file name on filesystem
|
|
|
|
- fname = os.path.basename(fsdb.get_file_path(hash_digest))
|
|
|
|
- if size is None:
|
|
|
|
- size = os.stat(fsdb.get_file_path(hash_digest)).st_size
|
|
|
|
- return 'retroshare://file?name=%s&size=%d&hash=%s' % (fname, size, hash_digest)
|
|
|
|
-
|
|
|
|
|
|
|
|
def main_file_publish(args):
|
|
def main_file_publish(args):
|
|
- ret = _file_publish(args, args.fnames)
|
|
|
|
|
|
+ ret = rsfiles.file_publish(args, args.fnames)
|
|
for filehash, fname in zip(ret, args.fnames):
|
|
for filehash, fname in zip(ret, args.fnames):
|
|
- print(color(filehash, fg='green') + ' \t%s' % fname)
|
|
|
|
- print(' ' + get_file_link(args, filehash, fname=fname))
|
|
|
|
|
|
+ print(color(filehash, fg="green") + " \t%s" % fname)
|
|
|
|
+ print(" " + rsfiles.get_file_link(args, filehash, fname=fname))
|
|
|
|
+
|
|
|
|
|
|
def get_parser():
|
|
def get_parser():
|
|
p = argparse.ArgumentParser()
|
|
p = argparse.ArgumentParser()
|
|
@@ -315,15 +224,9 @@ def get_parser():
|
|
files = p_sub.add_parser("file")
|
|
files = p_sub.add_parser("file")
|
|
files_sub = files.add_subparsers()
|
|
files_sub = files.add_subparsers()
|
|
files_list = files_sub.add_parser("publish")
|
|
files_list = files_sub.add_parser("publish")
|
|
- files_list.add_argument(
|
|
|
|
- "--fname",
|
|
|
|
- nargs="+",
|
|
|
|
- required=True,
|
|
|
|
- dest='fnames'
|
|
|
|
- )
|
|
|
|
|
|
+ files_list.add_argument("--fname", nargs="+", required=True, dest="fnames")
|
|
files_list.set_defaults(mainfunc=main_file_publish)
|
|
files_list.set_defaults(mainfunc=main_file_publish)
|
|
|
|
|
|
-
|
|
|
|
# TODO: channel rss -> read and convert to rss
|
|
# TODO: channel rss -> read and convert to rss
|
|
|
|
|
|
return p
|
|
return p
|