Ported to Python 3
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user