Ported to Python 3
This commit is contained in:
parent
87638269c8
commit
fc4548bbe5
@ -84,3 +84,7 @@ Users with write access can send files to bot.
|
||||
Users with delete access can delete and rename files.
|
||||
|
||||
Example of settings is [here](/settings.json)
|
||||
|
||||
## Hard Fork
|
||||
|
||||
https://git.plastiras.org/emdee/filebot
|
||||
|
32
bootstrap.py
32
bootstrap.py
@ -1,10 +1,19 @@
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
import random
|
||||
|
||||
global LOG
|
||||
import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
iNUM_NODES = 6
|
||||
|
||||
class Node(object):
|
||||
|
||||
def __init__(self, ip, port, tox_key, rand):
|
||||
self._ip, self._port, self._tox_key, self.rand = ip, port, tox_key, rand
|
||||
def __init__(self, ip, port, tox_key, rand=0):
|
||||
self._ip = ip
|
||||
self._port = port
|
||||
self._tox_key = tox_key
|
||||
self.rand = rand
|
||||
|
||||
def get_data(self):
|
||||
return self._ip, self._port, self._tox_key
|
||||
@ -12,6 +21,16 @@ class Node(object):
|
||||
|
||||
def node_generator():
|
||||
nodes = []
|
||||
try:
|
||||
from wrapper_tests.support_testing import generate_nodes
|
||||
all = generate_nodes()
|
||||
random.shuffle(all)
|
||||
for elt in all[:iNUM_NODES]:
|
||||
nodes.append(Node(*elt))
|
||||
return nodes
|
||||
except Exception as e:
|
||||
LOG.warn(e)
|
||||
# drop through
|
||||
ips = [
|
||||
"144.76.60.215", "23.226.230.47", "195.154.119.113", "biribiri.org",
|
||||
"46.38.239.179", "178.62.250.138", "130.133.110.14", "104.167.101.29",
|
||||
@ -76,8 +95,9 @@ def node_generator():
|
||||
"5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802",
|
||||
"31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E"
|
||||
]
|
||||
for i in xrange(len(ips)):
|
||||
nodes.append(Node(ips[i], ports[i], ids[i], random.randint(0, 1000000)))
|
||||
arr = sorted(nodes, key=lambda x: x.rand)[:4]
|
||||
for elem in arr:
|
||||
for i in range(len(ips)):
|
||||
nodes.append(Node(ips[i], ports[i], ids[i]) )
|
||||
arr = sorted(nodes)
|
||||
random.shuffle(arr)
|
||||
for elem in arr[:iNUM_NODES]:
|
||||
yield elem.get_data()
|
||||
|
33
bot.py
33
bot.py
@ -1,12 +1,16 @@
|
||||
from tox import Tox
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
from wrapper.tox import Tox
|
||||
import os
|
||||
from settings import *
|
||||
from toxcore_enums_and_consts import *
|
||||
from wrapper.toxcore_enums_and_consts import *
|
||||
from ctypes import *
|
||||
from util import Singleton, folder_size
|
||||
from file_transfers import *
|
||||
from collections import defaultdict
|
||||
|
||||
global LOG
|
||||
import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class Bot(Singleton):
|
||||
|
||||
@ -174,10 +178,10 @@ class Bot(Singleton):
|
||||
fl = ' '.join(message.split(' ')[2:])
|
||||
try:
|
||||
num = self._tox.friend_by_public_key(message.split(' ')[1][:TOX_PUBLIC_KEY_SIZE * 2])
|
||||
print num
|
||||
LOG.debug(num)
|
||||
self.send_file(settings['folder'] + '/' + fl, num)
|
||||
except Exception as ex:
|
||||
print ex
|
||||
LOG.warn(ex)
|
||||
self.send_message(friend_num, 'Friend not found'.encode('utf-8'))
|
||||
else:
|
||||
fl = ' '.join(message.split(' ')[2:])
|
||||
@ -289,7 +293,7 @@ class Bot(Singleton):
|
||||
:param tox_id: tox id of contact
|
||||
:param message: message
|
||||
"""
|
||||
print 'Friend request:', message
|
||||
LOG.info('Friend request:' +message)
|
||||
self._tox.friend_add_norequest(tox_id)
|
||||
settings = Settings.get_instance()
|
||||
# give friend default rights
|
||||
@ -395,6 +399,18 @@ def tox_factory(data=None, settings=None):
|
||||
:return: new tox instance
|
||||
"""
|
||||
if settings is None:
|
||||
if os.getenv('socks_proxy') != '':
|
||||
settings = {
|
||||
'ipv6_enabled': False,
|
||||
'udp_enabled': False,
|
||||
'proxy_type': 2,
|
||||
'proxy_host': b'127.0.0.1',
|
||||
'proxy_port': 9050,
|
||||
'start_port': 0,
|
||||
'end_port': 0,
|
||||
'tcp_port': 0
|
||||
}
|
||||
else:
|
||||
settings = {
|
||||
'ipv6_enabled': True,
|
||||
'udp_enabled': True,
|
||||
@ -421,4 +437,11 @@ def tox_factory(data=None, settings=None):
|
||||
tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['NONE']
|
||||
tox_options.contents.savedata_data = None
|
||||
tox_options.contents.savedata_length = 0
|
||||
# overrides
|
||||
tox_options.contents.local_discovery_enabled = False
|
||||
tox_options.contents.ipv6_enabled = False
|
||||
tox_options.contents.hole_punching_enabled = False
|
||||
|
||||
LOG.debug("wrapper.tox.Tox settings: " +repr(settings))
|
||||
|
||||
return Tox(tox_options)
|
||||
|
32
callbacks.py
32
callbacks.py
@ -1,8 +1,12 @@
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
from settings import Settings
|
||||
from bot import Bot
|
||||
from toxcore_enums_and_consts import *
|
||||
from tox import bin_to_string
|
||||
from wrapper.toxcore_enums_and_consts import *
|
||||
from wrapper.tox import bin_to_string
|
||||
|
||||
global LOG
|
||||
import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Callbacks - current user
|
||||
@ -14,7 +18,7 @@ def self_connection_status():
|
||||
Current user changed connection status (offline, UDP, TCP)
|
||||
"""
|
||||
def wrapped(tox, connection, user_data):
|
||||
print 'Connection status: ', str(connection)
|
||||
LOG.debug('Connection status: ' + str(connection))
|
||||
return wrapped
|
||||
|
||||
|
||||
@ -27,7 +31,7 @@ def friend_connection_status(tox, friend_num, new_status, user_data):
|
||||
"""
|
||||
Check friend's connection status (offline, udp, tcp)
|
||||
"""
|
||||
print "Friend #{} connected! Friend's status: {}".format(friend_num, new_status)
|
||||
LOG.info("Friend #{} connected! Friend's status: {}".format(friend_num, new_status))
|
||||
|
||||
|
||||
def friend_message():
|
||||
@ -35,7 +39,7 @@ def friend_message():
|
||||
New message from friend
|
||||
"""
|
||||
def wrapped(tox, friend_number, message_type, message, size, user_data):
|
||||
print message.decode('utf-8')
|
||||
LOG.info(message.decode('utf-8'))
|
||||
Bot.get_instance().new_message(friend_number, message.decode('utf-8'))
|
||||
# parse message
|
||||
return wrapped
|
||||
@ -62,7 +66,7 @@ def tox_file_recv(tox_link):
|
||||
def wrapped(tox, friend_number, file_number, file_type, size, file_name, file_name_size, user_data):
|
||||
profile = Bot.get_instance()
|
||||
if file_type == TOX_FILE_KIND['DATA']:
|
||||
print 'file'
|
||||
LOG.info('file')
|
||||
file_name = unicode(file_name[:file_name_size].decode('utf-8'))
|
||||
profile.incoming_file_transfer(friend_number, file_number, size, file_name)
|
||||
else: # AVATAR
|
||||
@ -109,13 +113,13 @@ def init_callbacks(tox):
|
||||
Initialization of all callbacks.
|
||||
:param tox: tox instance
|
||||
"""
|
||||
tox.callback_self_connection_status(self_connection_status(), 0)
|
||||
tox.callback_self_connection_status(self_connection_status())
|
||||
|
||||
tox.callback_friend_message(friend_message(), 0)
|
||||
tox.callback_friend_connection_status(friend_connection_status, 0)
|
||||
tox.callback_friend_request(friend_request, 0)
|
||||
tox.callback_friend_message(friend_message())
|
||||
tox.callback_friend_connection_status(friend_connection_status)
|
||||
tox.callback_friend_request(friend_request)
|
||||
|
||||
tox.callback_file_recv(tox_file_recv(tox), 0)
|
||||
tox.callback_file_recv_chunk(file_recv_chunk, 0)
|
||||
tox.callback_file_chunk_request(file_chunk_request, 0)
|
||||
tox.callback_file_recv_control(file_recv_control, 0)
|
||||
tox.callback_file_recv(tox_file_recv(tox))
|
||||
tox.callback_file_recv_chunk(file_recv_chunk)
|
||||
tox.callback_file_chunk_request(file_chunk_request)
|
||||
tox.callback_file_recv_control(file_recv_control)
|
||||
|
@ -1,8 +1,9 @@
|
||||
from toxcore_enums_and_consts import TOX_FILE_KIND, TOX_FILE_CONTROL
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
from wrapper.toxcore_enums_and_consts import TOX_FILE_KIND, TOX_FILE_CONTROL
|
||||
from os.path import basename, getsize
|
||||
from os import remove
|
||||
from time import time
|
||||
from tox import Tox
|
||||
from wrapper.tox import Tox
|
||||
|
||||
|
||||
TOX_FILE_TRANSFER_STATE = {
|
||||
|
46
main.py
46
main.py
@ -1,9 +1,40 @@
|
||||
from bootstrap import node_generator
|
||||
from bot import *
|
||||
from callbacks import init_callbacks
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
help - list of commands\n
|
||||
rights - get access rights\n
|
||||
files - show list of files (get access)\n
|
||||
id - get bot's id (get access)\n
|
||||
share <ToxID> <file_name> - send file to friend (get access)\n
|
||||
share --all <file_name> - send file to all friends (get access)\n
|
||||
size <file_name> - get size of file (get access)\n
|
||||
get <file_name> - get file with specified filename (get access)\n
|
||||
get --all - get all files (get access)\n
|
||||
stats - show statistics (write access)\n
|
||||
del <file_name> - remove file with specified filename (delete access)\n
|
||||
rename <file_name> --new <new_file_name> - rename file (delete access)\n
|
||||
user <ToxID> <rights> - new rights (example: rwdm) for user (masters only)\n
|
||||
status <new_status> - new status message (masters only)\n
|
||||
name <new_name> - new name (masters only)\n
|
||||
message <ToxID> <message_text> - send message to friend (masters only)\n
|
||||
message --all <message_text> - send message to all friends (masters only)\n
|
||||
stop - stop bot (masters only)\n
|
||||
fsize <folder_size_in_MB> - set folder size in MB (masters only)\n
|
||||
Users with write access can send files to bot.
|
||||
"""
|
||||
|
||||
import time
|
||||
import sys
|
||||
|
||||
from bootstrap import node_generator
|
||||
from bot import Bot, tox_factory, ProfileHelper
|
||||
from callbacks import init_callbacks
|
||||
from settings import Settings
|
||||
|
||||
global LOG
|
||||
import logging
|
||||
logging.basicConfig(level=10)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class FileBot(object):
|
||||
|
||||
@ -13,7 +44,7 @@ class FileBot(object):
|
||||
self.stop = False
|
||||
self.profile = None
|
||||
self.path = path
|
||||
print 'FileBot v0.1.2'
|
||||
LOG.info('FileBot v0.1.2+')
|
||||
|
||||
def main(self):
|
||||
self.tox = tox_factory(ProfileHelper.open_profile(self.path))
|
||||
@ -23,7 +54,7 @@ class FileBot(object):
|
||||
self.tox.bootstrap(*data)
|
||||
settings = Settings()
|
||||
self.profile = Bot(self.tox)
|
||||
print 'Iterate'
|
||||
LOG.debug('Iterate')
|
||||
try:
|
||||
while not self.stop:
|
||||
self.tox.iterate()
|
||||
@ -36,10 +67,9 @@ class FileBot(object):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
if len(sys.argv) <= 1:
|
||||
raise IOError('Path to save file not found')
|
||||
path = sys.argv[1]
|
||||
bot = FileBot(path)
|
||||
bot.main()
|
||||
else:
|
||||
raise IOError('Path to save file not found')
|
||||
|
||||
|
20
settings.py
20
settings.py
@ -1,24 +1,28 @@
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
import json
|
||||
import os
|
||||
import locale
|
||||
from util import Singleton, curr_directory
|
||||
from toxcore_enums_and_consts import *
|
||||
from wrapper.toxcore_enums_and_consts import *
|
||||
|
||||
global LOG
|
||||
import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class Settings(Singleton, dict):
|
||||
|
||||
def __init__(self):
|
||||
self.path = curr_directory() + '/settings.json'
|
||||
self.path = os.path.join(curr_directory(), 'settings.json')
|
||||
if os.path.isfile(self.path):
|
||||
with open(self.path) as fl:
|
||||
data = fl.read()
|
||||
super(self.__class__, self).__init__(json.loads(data))
|
||||
else:
|
||||
super(self.__class__, self).__init__(Settings.get_default_settings())
|
||||
self['read'] = map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['read']))
|
||||
self['write'] = map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['write']))
|
||||
self['delete'] = map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['delete']))
|
||||
self['master'] = map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['master']))
|
||||
self['read'] = list(map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['read'])))
|
||||
self['write'] = list(map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['write'])))
|
||||
self['delete'] = list(map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['delete'])))
|
||||
self['master'] = list(map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['master'])))
|
||||
if self['folder'][-1] == '/' or self['folder'][-1] == '\\':
|
||||
self['folder'] = self['folder'][:-1]
|
||||
self.save()
|
||||
@ -31,12 +35,13 @@ class Settings(Singleton, dict):
|
||||
'delete': [],
|
||||
'master': [],
|
||||
'folder': curr_directory(),
|
||||
'folder_save': curr_directory(),
|
||||
'auto_rights': 'r',
|
||||
'size': 500
|
||||
}
|
||||
|
||||
def save(self):
|
||||
print 'Saving'
|
||||
LOG.debug('Saving')
|
||||
text = json.dumps(self)
|
||||
with open(self.path, 'w') as fl:
|
||||
fl.write(text)
|
||||
@ -49,7 +54,6 @@ class ProfileHelper(object):
|
||||
|
||||
@staticmethod
|
||||
def open_profile(path):
|
||||
path = path.decode(locale.getpreferredencoding())
|
||||
ProfileHelper._path = path
|
||||
with open(ProfileHelper._path, 'rb') as fl:
|
||||
data = fl.read()
|
||||
|
4
util.py
4
util.py
@ -1,3 +1,5 @@
|
||||
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
|
||||
@ -23,7 +25,7 @@ class Singleton(object):
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not hasattr(cls, '_instance'):
|
||||
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
|
||||
cls._instance = super(Singleton, cls).__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
@classmethod
|
||||
|
Loading…
Reference in New Issue
Block a user