<commit_before>#!/usr/bin/python
# cmd_line_json.py
#
# Copyright (C) 2008-2018 <NAME>, https://bitdust.io
#
# This file (cmd_line_json.py) is part of BitDust Software.
#
# BitDust is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BitDust Software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with BitDust Software.  If not, see <http://www.gnu.org/licenses/>.
#
# Please contact us if you have any questions at <EMAIL>
#
#
#
#

"""
..

module:: cmd_line_json
"""

#------------------------------------------------------------------------------

from __future__ import absolute_import
from __future__ import print_function
from six.moves import range

#------------------------------------------------------------------------------

import os
import sys

#------------------------------------------------------------------------------

from lib import strng

from lib import jsontemplate

from interface import cmd_line_json_templates as templ

#------------------------------------------------------------------------------


def parser():
    """
    Create an ``optparse.OptionParser`` object to read command line arguments.
    """
    from optparse import OptionParser, OptionGroup
    from main.help import usage_text
    parser = OptionParser(usage=usage_text())
    group = OptionGroup(parser, "Logs")
    group.add_option('-d', '--debug',
                     dest='debug',
                     type='int',
                     help='set debug level',)
    group.add_option('-q', '--quite',
                     dest='quite',
                     action='store_true',
                     help='quite mode, do not print any messages to stdout',)
    group.add_option('-v', '--verbose',
                     dest='verbose',
                     action='store_true',
                     help='verbose mode, print more messages',)
    group.add_option('-n', '--no-logs',
                     dest='no_logs',
                     action='store_true',
                     help='do not use logs',)
    group.add_option('-o', '--output',
                     dest='output',
                     type='string',
                     help='print log messages to the file',)
    group.add_option('--twisted',
                     dest='twisted',
                     action='store_true',
                     help='show twisted log messages too',)
    parser.add_option_group(group)
    return parser


def override_options(opts, args):
    """
    The program can replace some user options by values passed via command
    line.

    This method return a dictionary where is stored a key-value pairs
    for new options.
    """
    overDict = {}
    if opts.debug or str(opts.debug) == '0':
        overDict['logs.debug-level'] = str(opts.debug)
    return overDict

#------------------------------------------------------------------------------


def print_copyright():
    """
    Prints the copyright string.
    """
    print_text('Copyright BitDust, 2014. All rights reserved.')


def print_text(msg, nl='\n'):
    """
    Send some output to the console.
    """
    sys.stdout.write(msg + nl)
    sys.stdout.flush()


def print_exception():
    """
    This is second most common method in the project.

    Print detailed info about last exception to the logs.
    """
    import traceback
    _, value, trbk = sys.exc_info()
    try:
        excArgs = value.__dict__["args"]
    except KeyError:
        excArgs = ''
    excTb = traceback.format_tb(trbk)
    s = 'Exception: <' + str(value) + '>\n'
    if excArgs:
        s += '  args:' + excArgs + '\n'
    for l in excTb:
        s += l + '\n'
    sys.stdout.write(s)
    sys.stdout.flush()


def print_and_stop(result):
    """
    Print text to console and stop the reactor.
    """
    from twisted.internet import reactor
    import pprint
    pprint.pprint(result, indent=2,)
    reactor.stop()


def print_template(result, template):
    """
    Use json template to format the text and print to STDOUT.
    """
    # print result
    # print template
    sys.stdout.write(template.expand(result))
    sys.stdout.flush()
    # import pprint
    # sys.stdout.write(pprint.pformat(result, 4, 80))


def print_template_and_stop(result, template):
    """
    Print text with json template formatting and stop the reactor.
    """
    from twisted.internet import reactor
    print_template(result, template)
    reactor.stop()


def fail_and_stop(err):
    """
    Send error message to STDOUT and stop the reactor.
    """
    from twisted.internet import reactor
    try:
        print_text(err.getErrorMessage())
    except:
        print(err)
    reactor.stop()

#------------------------------------------------------------------------------

def call_rest_http_method(path, method='GET', params=None, data=None, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    from twisted.web import client, http_headers
    from main import settings
    # TODO: add body and params handling
    return client.Agent(reactor).request(
        method=method,
        uri='http://127.0.0.1:%s/%s' % (settings.getRESTHTTPServerPort(), path),
        headers=http_headers.Headers({
            'User-Agent': ['Twisted Web Client Example'],
            'Content-Type': ['application/json'],
        }),
    )

#------------------------------------------------------------------------------

def call_jsonrpc_method(method, *args, **kwargs):
    """
    Method to communicate with existing BitDust process.

    Reads port number of the local RPC server and do the request.
    """
    from system import bpio
    from main import settings
    from lib.fastjsonrpc.client import Proxy as jsonProxy
    try:
        local_port = int(bpio.ReadTextFile(settings.LocalJsonRPCPortFilename()))
    except:
        local_port = settings.DefaultJsonRPCPort()
    proxy = jsonProxy('http://127.0.0.1:' + str(local_port))
    return proxy.callRemote(method, *args, **kwargs)


def call_jsonrpc_method_and_stop(method, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(print_and_stop)
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0


def call_jsonrpc_method_template_and_stop(method, template, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(print_template_and_stop, template)
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0


def call_jsonrpc_method_transform_template_and_stop(method, template, transform, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(lambda result: print_template_and_stop(transform(result), template))
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0

#------------------------------------------------------------------------------


def kill():
    """
    Kill all running BitDust processes (except current).
    """
    import time
    from system import bpio
    total_count = 0
    found = False
    while True:
        appList = bpio.find_process([
            'bitdustnode.exe',
            'BitDustNode.exe',
            'bpmain.py',
            'bitdust.py',
            'regexp:^/usr/bin/python.*bitdust.*$',
            'bppipe.py',
            'bptester.py',
        ])
        if len(appList) > 0:
            found = True
        for pid in appList:
            print_text('trying to stop pid %d' % pid)
            bpio.kill_process(pid)
        if len(appList) == 0:
            if found:
                print_text('BitDust stopped\n')
            else:
                print_text('BitDust was not started\n')
            return 0
        total_count += 1
        if total_count > 10:
            print_text('some BitDust process found, but can not stop it\n')
            return 1
        time.sleep(1)


def wait_then_kill(x):
    """
    For correct shutdown of the program need to send a URL request to the HTTP
    server:: http://localhost:<random port>/?action=exit.

    After receiving such request the program will call
    ``p2p.init_shutdown.shutdown()`` method and stops. But if the main
    process was blocked it needs to be killed with system "kill"
    procedure. This method will wait for 10 seconds and then call method
    ``kill()``.
    """
    import time
    from twisted.internet import reactor
    from logs import lg
    from system import bpio
    total_count = 0
    while True:
        appList = bpio.find_process([
            'bitdustnode.exe',
            'BitDustNode.exe',
            'bpmain.py',
            'bitdust.py',
            'regexp:^/usr/bin/python.*bitdust.*$',
            'bppipe.py',
            'bptester.py',
        ])
        if len(appList) == 0:
            print_text('DONE')
            reactor.stop()
            return 0
        total_count += 1
        if total_count > 10:
            print_text('not responding, KILLING ...')
            ret = kill()
            reactor.stop()
            return ret
        time.sleep(1)

#------------------------------------------------------------------------------


def run_now(opts, args):
    from system import bpio
    from logs import lg
    lg.life_begins()
    if opts.no_logs:
        lg.disable_logs()
    overDict = override_options(opts, args)
    from main.bpmain import run
    ui = ''
    if len(args) > 0 and args[0].lower() in ['restart', ]:
        ui = 'show'
    ret = run(ui, opts, args, overDict)
    bpio.shutdown()
    return ret

#------------------------------------------------------------------------------


def cmd_deploy(opts, args, overDict):
    from system import deploy
    return deploy.run(args)

#------------------------------------------------------------------------------


def cmd_reconnect(opts, args, overDict):
    tpl = jsontemplate.Template(templ.TPL_RAW)
    return call_jsonrpc_method_template_and_stop('reconnect', tpl)

#------------------------------------------------------------------------------


def cmd_identity(opts, args, overDict, running, executablePath):
    from userid import my_id
    from main import settings
    settings.init()
    my_id.init()

    if args[0] == 'idurl':
        if my_id.isLocalIdentityReady():
            print_text(my_id.getLocalID())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    if args[0] in ['globid', 'globalid', 'gid', 'glid', ] or (args[0] == 'id' and len(args) <= 1):
        if my_id.isLocalIdentityReady():
            print_text(my_id.getGlobalID())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    if len(args) == 1 or args[1].lower() in ['info', '?', 'show', 'print', ]:
        if my_id.isLocalIdentityReady():
            print_text(my_id.getLocalIdentity().serialize())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    from twisted.internet import reactor

    if args[1] in ['server', 'srv', ]:
        def _run_stand_alone_id_server():
            from logs import lg
            from userid import id_server
            lg.set_debug_level(settings.getDebugLevel())
            reactor.addSystemEventTrigger('before', 'shutdown', id_server.A().automat, 'shutdown')
            reactor.callWhenRunning(
                id_server.A, 'init', (settings.getIdServerWebPort(), settings.getIdServerTCPPort()))
            reactor.callLater(0, id_server.A, 'start')
            reactor.run()

        if len(args) <= 2:
            if not running:
                _run_stand_alone_id_server()
                return 0
            tpl = jsontemplate.Template(templ.TPL_SERVICE_INFO)
            return call_jsonrpc_method_template_and_stop('service_info', tpl, 'service_identity_server')
        if args[2] == 'stop':
            if not running:
                print_text('BitDust is not running at the moment\n')
                return 0
            tpl = jsontemplate.Template(templ.TPL_RAW)
            return call_jsonrpc_method_template_and_stop('service_stop', tpl, 'service_identity_server')
        if args[2] == 'start':
            if not running:
                _run_stand_alone_id_server()
                return 0
            tpl = jsontemplate.Template(templ.TPL_RAW)
            return call_jsonrpc_method_template_and_stop('service_start', tpl, 'service_identity_server')
        return 2

    def _register():
        if len(args) <= 2:
            return 2
        pksize = settings.getPrivateKeySize()
        if len(args) > 3:
            try:
                pksize = int(args[3])
            except:
                print_text('incorrect private key size\n')
                return 0
        from automats import automat
        from main import initializer
        from lib import misc
        from logs import lg
        if not misc.ValidUserName(args[2]):
            print_text('invalid user name')
            return 0
        automat.LifeBegins(lg.when_life_begins())
        automat.OpenLogFile(settings.AutomatsLog())
        initializer.A('run-cmd-line-register', {'username': args[2], 'pksize': pksize})
        reactor.run()
        automat.objects().clear()
        my_id.loadLocalIdentity()
        if my_id.isLocalIdentityReady():
            print_text('\n' + my_id.getLocalIdentity().serialize())
        else:
            print_text('identity creation FAILED')
        return 0

    def _recover():
        from system import bpio
        from lib import nameurl
        if len(args) < 3:
            return 2
        src = bpio.ReadTextFile(args[2])
        if len(src) > 1024 * 10:
            print_text('file is too big for private key')
            return 0
        try:
            lines = src.split(u'\n')
            idurl = lines[0]
            txt = u'\n'.join(lines[1:])
            if idurl != nameurl.FilenameUrl(nameurl.UrlFilename(idurl)):
                idurl = u''
                txt = src
        except:
            idurl = u''
            txt = src
        if not idurl and len(args) > 3:
            idurl = args[3]
        if not idurl:
            print_text('BitDust need to know your IDURL to recover your account\n')
            return 2
        from automats import automat
        from main import initializer
        from logs import lg
        automat.LifeBegins(lg.when_life_begins())
        automat.OpenLogFile(settings.AutomatsLog())
        initializer.A('run-cmd-line-recover', {u'idurl': idurl, u'keysrc': txt})
        reactor.run()
        automat.objects().clear()
        my_id.loadLocalIdentity()
        if my_id.isLocalIdentityReady():
            print_text('\n' + my_id.getLocalIdentity().serialize())
        else:
            print_text('identity recovery FAILED')
        return 0

    if args[1].lower() in ['create', 'new', 'register', 'generate', ]:
        if my_id.isLocalIdentityReady():
            print_text('local identity [%s] already exist\n' % my_id.getIDName())
            return 1
        if running:
            print_text('BitDust is running at the moment, need to stop the software first\n')
            return 0
        return _register()

    if len(args) >= 2 and args[1].lower() in ['bk', 'backup', 'save', ]:
        from interface import api
        key_id = 'master'
        key_json = api.key_get(key_id=key_id, include_private=True)
        if key_json['status'] != 'OK':
            print_text('\n'.join(key_json['errors']))
            return 1
        TextToSave = key_json['result'][0]['creator'] + u"\n" + key_json['result'][0]['private']
        if args[1] in ['bk', 'backup', 'save', ]:
            from system import bpio
            curpath = os.getcwd()<commit_msg>more logs for standalone id server<commit_after>#!/usr/bin/python
# cmd_line_json.py
#
# Copyright (C) 2008-2018 <NAME>, https://bitdust.io
#
# This file (cmd_line_json.py) is part of BitDust Software.
#
# BitDust is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BitDust Software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with BitDust Software.  If not, see <http://www.gnu.org/licenses/>.
#
# Please contact us if you have any questions at <EMAIL>
#
#
#
#

"""
..

module:: cmd_line_json
"""

#------------------------------------------------------------------------------

from __future__ import absolute_import
from __future__ import print_function
from six.moves import range

#------------------------------------------------------------------------------

import os
import sys

#------------------------------------------------------------------------------

from lib import strng

from lib import jsontemplate

from interface import cmd_line_json_templates as templ

#------------------------------------------------------------------------------


def parser():
    """
    Create an ``optparse.OptionParser`` object to read command line arguments.
    """
    from optparse import OptionParser, OptionGroup
    from main.help import usage_text
    parser = OptionParser(usage=usage_text())
    group = OptionGroup(parser, "Logs")
    group.add_option('-d', '--debug',
                     dest='debug',
                     type='int',
                     help='set debug level',)
    group.add_option('-q', '--quite',
                     dest='quite',
                     action='store_true',
                     help='quite mode, do not print any messages to stdout',)
    group.add_option('-v', '--verbose',
                     dest='verbose',
                     action='store_true',
                     help='verbose mode, print more messages',)
    group.add_option('-n', '--no-logs',
                     dest='no_logs',
                     action='store_true',
                     help='do not use logs',)
    group.add_option('-o', '--output',
                     dest='output',
                     type='string',
                     help='print log messages to the file',)
    group.add_option('--twisted',
                     dest='twisted',
                     action='store_true',
                     help='show twisted log messages too',)
    parser.add_option_group(group)
    return parser


def override_options(opts, args):
    """
    The program can replace some user options by values passed via command
    line.

    This method return a dictionary where is stored a key-value pairs
    for new options.
    """
    overDict = {}
    if opts.debug or str(opts.debug) == '0':
        overDict['logs.debug-level'] = str(opts.debug)
    return overDict

#------------------------------------------------------------------------------


def print_copyright():
    """
    Prints the copyright string.
    """
    print_text('Copyright BitDust, 2014. All rights reserved.')


def print_text(msg, nl='\n'):
    """
    Send some output to the console.
    """
    sys.stdout.write(msg + nl)
    sys.stdout.flush()


def print_exception():
    """
    This is second most common method in the project.

    Print detailed info about last exception to the logs.
    """
    import traceback
    _, value, trbk = sys.exc_info()
    try:
        excArgs = value.__dict__["args"]
    except KeyError:
        excArgs = ''
    excTb = traceback.format_tb(trbk)
    s = 'Exception: <' + str(value) + '>\n'
    if excArgs:
        s += '  args:' + excArgs + '\n'
    for l in excTb:
        s += l + '\n'
    sys.stdout.write(s)
    sys.stdout.flush()


def print_and_stop(result):
    """
    Print text to console and stop the reactor.
    """
    from twisted.internet import reactor
    import pprint
    pprint.pprint(result, indent=2,)
    reactor.stop()


def print_template(result, template):
    """
    Use json template to format the text and print to STDOUT.
    """
    # print result
    # print template
    sys.stdout.write(template.expand(result))
    sys.stdout.flush()
    # import pprint
    # sys.stdout.write(pprint.pformat(result, 4, 80))


def print_template_and_stop(result, template):
    """
    Print text with json template formatting and stop the reactor.
    """
    from twisted.internet import reactor
    print_template(result, template)
    reactor.stop()


def fail_and_stop(err):
    """
    Send error message to STDOUT and stop the reactor.
    """
    from twisted.internet import reactor
    try:
        print_text(err.getErrorMessage())
    except:
        print(err)
    reactor.stop()

#------------------------------------------------------------------------------

def call_rest_http_method(path, method='GET', params=None, data=None, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    from twisted.web import client, http_headers
    from main import settings
    # TODO: add body and params handling
    return client.Agent(reactor).request(
        method=method,
        uri='http://127.0.0.1:%s/%s' % (settings.getRESTHTTPServerPort(), path),
        headers=http_headers.Headers({
            'User-Agent': ['Twisted Web Client Example'],
            'Content-Type': ['application/json'],
        }),
    )

#------------------------------------------------------------------------------

def call_jsonrpc_method(method, *args, **kwargs):
    """
    Method to communicate with existing BitDust process.

    Reads port number of the local RPC server and do the request.
    """
    from system import bpio
    from main import settings
    from lib.fastjsonrpc.client import Proxy as jsonProxy
    try:
        local_port = int(bpio.ReadTextFile(settings.LocalJsonRPCPortFilename()))
    except:
        local_port = settings.DefaultJsonRPCPort()
    proxy = jsonProxy('http://127.0.0.1:' + str(local_port))
    return proxy.callRemote(method, *args, **kwargs)


def call_jsonrpc_method_and_stop(method, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(print_and_stop)
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0


def call_jsonrpc_method_template_and_stop(method, template, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(print_template_and_stop, template)
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0


def call_jsonrpc_method_transform_template_and_stop(method, template, transform, *args, **kwargs):
    """
    """
    from twisted.internet import reactor
    d = call_jsonrpc_method(method, *args, **kwargs)
    d.addCallback(lambda result: print_template_and_stop(transform(result), template))
    d.addErrback(fail_and_stop)
    reactor.run()
    return 0

#------------------------------------------------------------------------------


def kill():
    """
    Kill all running BitDust processes (except current).
    """
    import time
    from system import bpio
    total_count = 0
    found = False
    while True:
        appList = bpio.find_process([
            'bitdustnode.exe',
            'BitDustNode.exe',
            'bpmain.py',
            'bitdust.py',
            'regexp:^/usr/bin/python.*bitdust.*$',
            'bppipe.py',
            'bptester.py',
        ])
        if len(appList) > 0:
            found = True
        for pid in appList:
            print_text('trying to stop pid %d' % pid)
            bpio.kill_process(pid)
        if len(appList) == 0:
            if found:
                print_text('BitDust stopped\n')
            else:
                print_text('BitDust was not started\n')
            return 0
        total_count += 1
        if total_count > 10:
            print_text('some BitDust process found, but can not stop it\n')
            return 1
        time.sleep(1)


def wait_then_kill(x):
    """
    For correct shutdown of the program need to send a URL request to the HTTP
    server:: http://localhost:<random port>/?action=exit.

    After receiving such request the program will call
    ``p2p.init_shutdown.shutdown()`` method and stops. But if the main
    process was blocked it needs to be killed with system "kill"
    procedure. This method will wait for 10 seconds and then call method
    ``kill()``.
    """
    import time
    from twisted.internet import reactor
    from logs import lg
    from system import bpio
    total_count = 0
    while True:
        appList = bpio.find_process([
            'bitdustnode.exe',
            'BitDustNode.exe',
            'bpmain.py',
            'bitdust.py',
            'regexp:^/usr/bin/python.*bitdust.*$',
            'bppipe.py',
            'bptester.py',
        ])
        if len(appList) == 0:
            print_text('DONE')
            reactor.stop()
            return 0
        total_count += 1
        if total_count > 10:
            print_text('not responding, KILLING ...')
            ret = kill()
            reactor.stop()
            return ret
        time.sleep(1)

#------------------------------------------------------------------------------


def run_now(opts, args):
    from system import bpio
    from logs import lg
    lg.life_begins()
    if opts.no_logs:
        lg.disable_logs()
    overDict = override_options(opts, args)
    from main.bpmain import run
    ui = ''
    if len(args) > 0 and args[0].lower() in ['restart', ]:
        ui = 'show'
    ret = run(ui, opts, args, overDict)
    bpio.shutdown()
    return ret

#------------------------------------------------------------------------------


def cmd_deploy(opts, args, overDict):
    from system import deploy
    return deploy.run(args)

#------------------------------------------------------------------------------


def cmd_reconnect(opts, args, overDict):
    tpl = jsontemplate.Template(templ.TPL_RAW)
    return call_jsonrpc_method_template_and_stop('reconnect', tpl)

#------------------------------------------------------------------------------


def cmd_identity(opts, args, overDict, running, executablePath):
    from userid import my_id
    from main import settings
    settings.init()
    my_id.init()

    if args[0] == 'idurl':
        if my_id.isLocalIdentityReady():
            print_text(my_id.getLocalID())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    if args[0] in ['globid', 'globalid', 'gid', 'glid', ] or (args[0] == 'id' and len(args) <= 1):
        if my_id.isLocalIdentityReady():
            print_text(my_id.getGlobalID())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    if len(args) == 1 or args[1].lower() in ['info', '?', 'show', 'print', ]:
        if my_id.isLocalIdentityReady():
            print_text(my_id.getLocalIdentity().serialize())
        else:
            print_text('local identity is not valid or not exist')
        return 0

    from twisted.internet import reactor

    if args[1] in ['server', 'srv', ]:
        def _run_stand_alone_id_server():
            from logs import lg
            from userid import id_server
            lg.open_log_file(os.path.join(settings.LogsDir(), 'idserver.log'))
            lg.set_debug_level(settings.getDebugLevel())
            reactor.addSystemEventTrigger('before', 'shutdown', id_server.A().automat, 'shutdown')
            reactor.callWhenRunning(
                id_server.A, 'init', (settings.getIdServerWebPort(), settings.getIdServerTCPPort()))
            reactor.callLater(0, id_server.A, 'start')
            reactor.run()

        if len(args) <= 2:
            if not running:
                _run_stand_alone_id_server()
                return 0
            tpl = jsontemplate.Template(templ.TPL_SERVICE_INFO)
            return call_jsonrpc_method_template_and_stop('service_info', tpl, 'service_identity_server')
        if args[2] == 'stop':
            if not running:
                print_text('BitDust is not running at the moment\n')
                return 0
            tpl = jsontemplate.Template(templ.TPL_RAW)
            return call_jsonrpc_method_template_and_stop('service_stop', tpl, 'service_identity_server')
        if args[2] == 'start':
            if not running:
                _run_stand_alone_id_server()
                return 0
            tpl = jsontemplate.Template(templ.TPL_RAW)
            return call_jsonrpc_method_template_and_stop('service_start', tpl, 'service_identity_server')
        return 2

    def _register():
        if len(args) <= 2:
            return 2
        pksize = settings.getPrivateKeySize()
        if len(args) > 3:
            try:
                pksize = int(args[3])
            except:
                print_text('incorrect private key size\n')
                return 0
        from automats import automat
        from main import initializer
        from lib import misc
        from logs import lg
        if not misc.ValidUserName(args[2]):
            print_text('invalid user name')
            return 0
        automat.LifeBegins(lg.when_life_begins())
        automat.OpenLogFile(settings.AutomatsLog())
        initializer.A('run-cmd-line-register', {'username': args[2], 'pksize': pksize})
        reactor.run()
        automat.objects().clear()
        my_id.loadLocalIdentity()
        if my_id.isLocalIdentityReady():
            print_text('\n' + my_id.getLocalIdentity().serialize())
        else:
            print_text('identity creation FAILED')
        return 0

    def _recover():
        from system import bpio
        from lib import nameurl
        if len(args) < 3:
            return 2
        src = bpio.ReadTextFile(args[2])
        if len(src) > 1024 * 10:
            print_text('file is too big for private key')
            return 0
        try:
            lines = src.split('\n')
            idurl = lines[0]
            txt = '\n'.join(lines[1:])
            if idurl != nameurl.FilenameUrl(nameurl.UrlFilename(idurl)):
                idurl = ''
                txt = src
        except:
            idurl = ''
            txt = src
        if not idurl and len(args) > 3:
            idurl = args[3]
        if not idurl:
            print_text('BitDust need to know your IDURL to recover your account\n')
            return 2
        from automats import automat
        from main import initializer
        from logs import lg
        automat.LifeBegins(lg.when_life_begins())
        automat.OpenLogFile(settings.AutomatsLog())
        initializer.A('run-cmd-line-recover', {'idurl': idurl, 'keysrc': txt})
        reactor.run()
        automat.objects().clear()
        my_id.loadLocalIdentity()
        if my_id.isLocalIdentityReady():
            print_text('\n' + my_id.getLocalIdentity().serialize())
        else:
            print_text('identity recovery FAILED')
        return 0

    if args[1].lower() in ['create', 'new', 'register', 'generate', ]:
        if my_id.isLocalIdentityReady():
            print_text('local identity [%s] already exist\n' % my_id.getIDName())
            return 1
        if running:
            print_text('BitDust is running at the moment, need to stop the software first\n')
            return 0
        return _register()

    if len(args) >= 2 and args[1].lower() in ['bk', 'backup', 'save', ]:
        from interface import api
        key_id = 'master'
        key_json = api.key_get(key_id=key_id, include_private=True)
        if key_json['status'] != 'OK':
            print_text('\n'.join(key_json['errors']))
            return 1
        TextToSave = key_json['result'][0]['creator'] + u"\n" + key_json['result'][0]['private']
        if args[1] in ['bk', 'backup', 'save', ]:
            from system import bpio
            curpath = os.getcwd()
{'fraction_non_alphanumeric': 0.16083787591106755, 'fraction_numerical': 0.006492313345991303, 'mean_word_length': 1.8562057202833901, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7558042', 'n_tokens_mistral': 9418, 'n_tokens_neox': 9076, 'n_words': 2498}