Compare commits

..

10 Commits
v0.1 ... master

Author SHA1 Message Date
emdee
0801537da3 EOF 2022-10-11 10:51:16 +00:00
emdee
fc4548bbe5 Ported to Python 3 2022-10-06 13:44:35 +00:00
Ingvar
87638269c8 Merge pull request #2 from wdbm/master
fix import of os.remove
2017-07-11 11:14:53 -07:00
Will Breaden Madden
3e67104820 fix import of os.remove 2017-07-11 17:17:41 +01:00
ingvar1995
80c2e620bd v 0.2.1 2016-10-03 00:24:34 +03:00
ingvar1995
3ea8c049c5 max folder size 2016-10-02 20:19:39 +03:00
ingvar1995
862d6a170e Merge branch 'master' of https://github.com/ingvar1995/filebot 2016-05-03 20:07:12 +03:00
ingvar1995
4582f6dd9d profile saving 2016-05-03 20:05:37 +03:00
Ingvar
92d4deadc2 Readme - commands fix 2016-05-02 12:21:25 +03:00
ingvar1995
59c72486f4 wrapper and docs update. 2016-04-30 15:18:15 +03:00
12 changed files with 235 additions and 112 deletions

View File

@ -15,10 +15,18 @@ Based on [toxygen](https://github.com/xveduk/toxygen/) toxcore wrapper
1. [Download and install latest Python 2.7](https://www.python.org/downloads/windows/) 1. [Download and install latest Python 2.7](https://www.python.org/downloads/windows/)
2. [Download file bot](https://github.com/ingvar1995/filebot/archive/master.zip) 2. [Download file bot](https://github.com/ingvar1995/filebot/archive/master.zip)
3. Unpack archive 3. Unpack archive
4. Download latest [libtox.dll](https://build.tox.chat/view/libtoxcore/job/libtoxcore_build_windows_x86_shared_release/lastSuccessfulBuild/artifact/libtoxcore_build_windows_x86_shared_release.zip) build, download latest [libsodium.a](https://build.tox.chat/view/libsodium/job/libsodium_build_windows_x86_static_release/lastSuccessfulBuild/artifact/libsodium_build_windows_x86_static_release.zip) build, put it into libs\ 4. Download latest libtox.dll build, download latest libsodium.a build, put it into \libs\
5. Run app: 5. Run app:
``python main.py path_to_profile`` ``python main.py path_to_profile``
[libtox.dll for 32-bit Python](https://build.tox.chat/view/libtoxcore/job/libtoxcore_build_windows_x86_shared_release/lastSuccessfulBuild/artifact/libtoxcore_build_windows_x86_shared_release.zip)
[libtox.dll for 64-bit Python](https://build.tox.chat/view/libtoxcore/job/libtoxcore_build_windows_x86-64_shared_release/lastSuccessfulBuild/artifact/libtoxcore_build_windows_x86-64_shared_release.zip)
[libsodium.a for 32-bit Python](https://build.tox.chat/view/libsodium/job/libsodium_build_windows_x86_static_release/lastSuccessfulBuild/artifact/libsodium_build_windows_x86_static_release.zip)
[libsodium.a for 64-bit Python](https://build.tox.chat/view/libsodium/job/libsodium_build_windows_x86-64_static_release/lastSuccessfulBuild/artifact/libsodium_build_windows_x86-64_static_release.zip)
### Linux ### Linux
@ -30,6 +38,7 @@ Based on [toxygen](https://github.com/xveduk/toxygen/) toxcore wrapper
``python main.py path_to_profile`` ``python main.py path_to_profile``
# Commands: # Commands:
```
help - list of commands help - list of commands
rights - get access rights rights - get access rights
@ -66,5 +75,18 @@ message --all <message_text> - send message to all friends (masters only)
stop - stop bot (masters only) stop - stop bot (masters only)
fsize <size_in_MB> - sets size of shared folder (masters only)
```
Users with write access can send files to bot. 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
Work on this project is suspended until the MultiDevice problem is solved.

0
__init__.py Normal file
View File

View File

@ -1,9 +1,19 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import random import random
global LOG
import logging
LOG = logging.getLogger(__name__)
iNUM_NODES = 6
class Node(object): 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): def get_data(self):
return self._ip, self._port, self._tox_key return self._ip, self._port, self._tox_key
@ -11,6 +21,16 @@ class Node(object):
def node_generator(): def node_generator():
nodes = [] 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 = [ ips = [
"144.76.60.215", "23.226.230.47", "195.154.119.113", "biribiri.org", "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", "46.38.239.179", "178.62.250.138", "130.133.110.14", "104.167.101.29",
@ -75,13 +95,9 @@ def node_generator():
"5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802", "5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802",
"31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E" "31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E"
] ]
for i in xrange(len(ips)): for i in range(len(ips)):
nodes.append(Node(ips[i], ports[i], ids[i], random.randint(0, 1000000))) nodes.append(Node(ips[i], ports[i], ids[i]) )
arr = sorted(nodes, key=lambda x: x.rand)[:4] arr = sorted(nodes)
for elem in arr: random.shuffle(arr)
for elem in arr[:iNUM_NODES]:
yield elem.get_data() yield elem.get_data()
if __name__ == "__main__":
for elem in node_generator():
print str(elem)

58
bot.py
View File

@ -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 import os
from settings import * from settings import *
from toxcore_enums_and_consts import * from wrapper.toxcore_enums_and_consts import *
from ctypes import * from ctypes import *
from util import log, Singleton from util import Singleton, folder_size
from file_transfers import * from file_transfers import *
from collections import defaultdict from collections import defaultdict
global LOG
import logging
LOG = logging.getLogger(__name__)
class Bot(Singleton): class Bot(Singleton):
@ -50,7 +54,7 @@ class Bot(Singleton):
elif '.' in last_part: elif '.' in last_part:
index = last_part.index('.') index = last_part.index('.')
else: else:
index = TOX_MAX_MESSAGE_LENGTH - size index = TOX_MAX_MESSAGE_LENGTH - size - 1
index += size + 1 index += size + 1
self._tox.friend_send_message(number, message_type, message[:index]) self._tox.friend_send_message(number, message_type, message[:index])
message = message[index:] message = message[index:]
@ -62,7 +66,7 @@ class Bot(Singleton):
:param friend_num: number of friend who sent message :param friend_num: number of friend who sent message
:param message: text of message :param message: text of message
""" """
id = self._tox.friend_get_public_key(friend_num) id = self._tox.friend_get_public_key(friend_num) # public key of user
settings = Settings.get_instance() settings = Settings.get_instance()
message = message.strip() message = message.strip()
# message parsing # message parsing
@ -112,6 +116,7 @@ class Bot(Singleton):
message <ToxID> <message_text> - send message to friend (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 message --all <message_text> - send message to all friends (masters only)\n
stop - stop bot (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. Users with write access can send files to bot.
""".encode('utf-8')) """.encode('utf-8'))
elif message == 'rights': # get rights elif message == 'rights': # get rights
@ -173,10 +178,10 @@ class Bot(Singleton):
fl = ' '.join(message.split(' ')[2:]) fl = ' '.join(message.split(' ')[2:])
try: try:
num = self._tox.friend_by_public_key(message.split(' ')[1][:TOX_PUBLIC_KEY_SIZE * 2]) 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) self.send_file(settings['folder'] + '/' + fl, num)
except Exception as ex: except Exception as ex:
print ex LOG.warn(ex)
self.send_message(friend_num, 'Friend not found'.encode('utf-8')) self.send_message(friend_num, 'Friend not found'.encode('utf-8'))
else: else:
fl = ' '.join(message.split(' ')[2:]) fl = ' '.join(message.split(' ')[2:])
@ -216,7 +221,7 @@ class Bot(Singleton):
elif bytes_size < 1024 * 1024: elif bytes_size < 1024 * 1024:
size = u'{} KB'.format(bytes_size / 1024) size = u'{} KB'.format(bytes_size / 1024)
else: else:
size = u'{} MB'.format(bytes_size / 1024 * 1024) size = u'{} MB'.format(bytes_size / (1024 * 1024))
s = u'Size: {} ({} bytes)'.format(size, bytes_size) s = u'Size: {} ({} bytes)'.format(size, bytes_size)
self.send_message(friend_num, s.encode('utf-8')) self.send_message(friend_num, s.encode('utf-8'))
elif message.startswith('message '): # send message to friend (all friends) elif message.startswith('message '): # send message to friend (all friends)
@ -264,6 +269,17 @@ class Bot(Singleton):
raise SystemExit() raise SystemExit()
else: else:
self.send_message(friend_num, 'Not enough rights'.encode('utf-8')) self.send_message(friend_num, 'Not enough rights'.encode('utf-8'))
elif message.startswith('fsize '):
if id not in settings['master']:
self.send_message(friend_num, 'Not enough rights'.encode('utf-8'))
else:
try:
size = int(message[6:])
settings['size'] = max(size, 10)
settings.save()
self.send_message(friend_num, 'Size was set'.encode('utf-8'))
except:
self.send_message(friend_num, 'Wrong command'.encode('utf-8'))
else: else:
self.send_message(friend_num, 'Wrong command'.encode('utf-8')) self.send_message(friend_num, 'Wrong command'.encode('utf-8'))
@ -277,6 +293,7 @@ class Bot(Singleton):
:param tox_id: tox id of contact :param tox_id: tox id of contact
:param message: message :param message: message
""" """
LOG.info('Friend request:' +message)
self._tox.friend_add_norequest(tox_id) self._tox.friend_add_norequest(tox_id)
settings = Settings.get_instance() settings = Settings.get_instance()
# give friend default rights # give friend default rights
@ -289,6 +306,8 @@ class Bot(Singleton):
if 'm' in settings['auto_rights'] and tox_id not in settings['master']: if 'm' in settings['auto_rights'] and tox_id not in settings['master']:
settings['master'].append(tox_id) settings['master'].append(tox_id)
settings.save() settings.save()
data = self._tox.get_savedata()
ProfileHelper.save_profile(data)
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# File transfers support # File transfers support
@ -304,7 +323,9 @@ class Bot(Singleton):
""" """
id = self._tox.friend_get_public_key(friend_number) id = self._tox.friend_get_public_key(friend_number)
settings = Settings.get_instance() settings = Settings.get_instance()
if id in settings['write']: fsize = folder_size(settings['folder']) + size
max_folder_size = settings['size'] * 1024 * 1024
if id in settings['write'] and fsize <= max_folder_size:
path = settings['folder'] path = settings['folder']
new_file_name, i = file_name, 1 new_file_name, i = file_name, 1
while os.path.isfile(path + '/' + new_file_name): # file with same name already exists while os.path.isfile(path + '/' + new_file_name): # file with same name already exists
@ -378,6 +399,18 @@ def tox_factory(data=None, settings=None):
:return: new tox instance :return: new tox instance
""" """
if settings is None: 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 = { settings = {
'ipv6_enabled': True, 'ipv6_enabled': True,
'udp_enabled': True, 'udp_enabled': True,
@ -404,4 +437,11 @@ def tox_factory(data=None, settings=None):
tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['NONE'] tox_options.contents.savedata_type = TOX_SAVEDATA_TYPE['NONE']
tox_options.contents.savedata_data = None tox_options.contents.savedata_data = None
tox_options.contents.savedata_length = 0 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) return Tox(tox_options)

View File

@ -1,8 +1,12 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from settings import Settings from settings import Settings
from bot import Bot from bot import Bot
from toxcore_enums_and_consts import * from wrapper.toxcore_enums_and_consts import *
from tox import bin_to_string from wrapper.tox import bin_to_string
global LOG
import logging
LOG = logging.getLogger(__name__)
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Callbacks - current user # Callbacks - current user
@ -14,7 +18,7 @@ def self_connection_status():
Current user changed connection status (offline, UDP, TCP) Current user changed connection status (offline, UDP, TCP)
""" """
def wrapped(tox, connection, user_data): def wrapped(tox, connection, user_data):
print 'Connection status: ', str(connection) LOG.debug('Connection status: ' + str(connection))
return wrapped 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) 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(): def friend_message():
@ -35,7 +39,7 @@ def friend_message():
New message from friend New message from friend
""" """
def wrapped(tox, friend_number, message_type, message, size, user_data): 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')) Bot.get_instance().new_message(friend_number, message.decode('utf-8'))
# parse message # parse message
return wrapped 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): def wrapped(tox, friend_number, file_number, file_type, size, file_name, file_name_size, user_data):
profile = Bot.get_instance() profile = Bot.get_instance()
if file_type == TOX_FILE_KIND['DATA']: if file_type == TOX_FILE_KIND['DATA']:
print 'file' LOG.info('file')
file_name = unicode(file_name[:file_name_size].decode('utf-8')) file_name = unicode(file_name[:file_name_size].decode('utf-8'))
profile.incoming_file_transfer(friend_number, file_number, size, file_name) profile.incoming_file_transfer(friend_number, file_number, size, file_name)
else: # AVATAR else: # AVATAR
@ -109,13 +113,13 @@ def init_callbacks(tox):
Initialization of all callbacks. Initialization of all callbacks.
:param tox: tox instance :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_message(friend_message())
tox.callback_friend_connection_status(friend_connection_status, 0) tox.callback_friend_connection_status(friend_connection_status)
tox.callback_friend_request(friend_request, 0) tox.callback_friend_request(friend_request)
tox.callback_file_recv(tox_file_recv(tox), 0) tox.callback_file_recv(tox_file_recv(tox))
tox.callback_file_recv_chunk(file_recv_chunk, 0) tox.callback_file_recv_chunk(file_recv_chunk)
tox.callback_file_chunk_request(file_chunk_request, 0) tox.callback_file_chunk_request(file_chunk_request)
tox.callback_file_recv_control(file_recv_control, 0) tox.callback_file_recv_control(file_recv_control)

View File

@ -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.path import basename, getsize
from os import remove from os import remove
from time import time from time import time
from tox import Tox from wrapper.tox import Tox
TOX_FILE_TRANSFER_STATE = { TOX_FILE_TRANSFER_STATE = {
@ -25,7 +26,7 @@ class FileTransfer(object):
self.state = TOX_FILE_TRANSFER_STATE['RUNNING'] self.state = TOX_FILE_TRANSFER_STATE['RUNNING']
self._file_number = file_number self._file_number = file_number
self._creation_time = time() self._creation_time = time()
self._size = float(size) self._size = size
self._done = 0 self._done = 0
def set_tox(self, tox): def set_tox(self, tox):
@ -123,3 +124,6 @@ class ReceiveTransfer(FileTransfer):
if position + l > self._file_size: if position + l > self._file_size:
self._file_size = position + l self._file_size = position + l
self._done += l self._done += l
if self._done > self._size:
self.cancel()
remove(self._path)

46
main.py
View File

@ -1,9 +1,40 @@
from bootstrap import node_generator # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from bot import *
from callbacks import init_callbacks """
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 time
import sys 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): class FileBot(object):
@ -13,7 +44,7 @@ class FileBot(object):
self.stop = False self.stop = False
self.profile = None self.profile = None
self.path = path self.path = path
print 'FileBot v0.1' LOG.info('FileBot v0.1.2+')
def main(self): def main(self):
self.tox = tox_factory(ProfileHelper.open_profile(self.path)) self.tox = tox_factory(ProfileHelper.open_profile(self.path))
@ -23,7 +54,7 @@ class FileBot(object):
self.tox.bootstrap(*data) self.tox.bootstrap(*data)
settings = Settings() settings = Settings()
self.profile = Bot(self.tox) self.profile = Bot(self.tox)
print 'Iterate' LOG.debug('Iterate')
try: try:
while not self.stop: while not self.stop:
self.tox.iterate() self.tox.iterate()
@ -36,10 +67,9 @@ class FileBot(object):
if __name__ == '__main__': 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] path = sys.argv[1]
bot = FileBot(path) bot = FileBot(path)
bot.main() bot.main()
else:
raise IOError('Path to save file not found')

View File

@ -1 +1 @@
{"write": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"], "auto_rights": "r", "master": [], "read": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"], "folder": "/home/tox_user/tox/shared", "delete": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"]} {"write": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"], "auto_rights": "r", "master": [], "read": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"], "folder": "/home/tox_user/tox/shared", "size": 500, "delete": ["56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855"]}

View File

@ -1,25 +1,28 @@
from platform import system # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import json import json
import os import os
import locale import locale
from util import Singleton, curr_directory 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): class Settings(Singleton, dict):
def __init__(self): def __init__(self):
self.path = curr_directory() + '/settings.json' self.path = os.path.join(curr_directory(), 'settings.json')
if os.path.isfile(self.path): if os.path.isfile(self.path):
with open(self.path) as fl: with open(self.path) as fl:
data = fl.read() data = fl.read()
super(self.__class__, self).__init__(json.loads(data)) super(self.__class__, self).__init__(json.loads(data))
else: else:
super(self.__class__, self).__init__(Settings.get_default_settings()) super(self.__class__, self).__init__(Settings.get_default_settings())
self['read'] = map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['read'])) self['read'] = list(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['write'] = list(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['delete'] = list(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['master'] = list(map(lambda x: x[:TOX_PUBLIC_KEY_SIZE * 2], set(self['master'])))
if self['folder'][-1] == '/' or self['folder'][-1] == '\\': if self['folder'][-1] == '/' or self['folder'][-1] == '\\':
self['folder'] = self['folder'][:-1] self['folder'] = self['folder'][:-1]
self.save() self.save()
@ -32,11 +35,13 @@ class Settings(Singleton, dict):
'delete': [], 'delete': [],
'master': [], 'master': [],
'folder': curr_directory(), 'folder': curr_directory(),
'auto_rights': 'r' 'folder_save': curr_directory(),
'auto_rights': 'r',
'size': 500
} }
def save(self): def save(self):
print 'Saving' LOG.debug('Saving')
text = json.dumps(self) text = json.dumps(self)
with open(self.path, 'w') as fl: with open(self.path, 'w') as fl:
fl.write(text) fl.write(text)
@ -49,7 +54,6 @@ class ProfileHelper(object):
@staticmethod @staticmethod
def open_profile(path): def open_profile(path):
path = path.decode(locale.getpreferredencoding())
ProfileHelper._path = path ProfileHelper._path = path
with open(ProfileHelper._path, 'rb') as fl: with open(ProfileHelper._path, 'rb') as fl:
data = fl.read() data = fl.read()

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from ctypes import c_char_p, Structure, CDLL, c_bool, addressof, c_int, c_size_t, POINTER, c_uint16, c_void_p, c_uint64 from ctypes import c_char_p, Structure, CDLL, c_bool, byref, c_int, c_size_t, POINTER, c_uint16, c_void_p, c_uint64
from ctypes import create_string_buffer, ArgumentError, CFUNCTYPE, c_uint32, sizeof, c_uint8 from ctypes import create_string_buffer, ArgumentError, CFUNCTYPE, c_uint32, sizeof, c_uint8
from platform import system from platform import system
from toxcore_enums_and_consts import * from toxcore_enums_and_consts import *
@ -62,7 +62,7 @@ class Tox(object):
else: else:
tox_err_new = c_int() tox_err_new = c_int()
Tox.libtoxcore.tox_new.restype = POINTER(c_void_p) Tox.libtoxcore.tox_new.restype = POINTER(c_void_p)
self._tox_pointer = Tox.libtoxcore.tox_new(tox_options, addressof(tox_err_new)) self._tox_pointer = Tox.libtoxcore.tox_new(tox_options, byref(tox_err_new))
tox_err_new = tox_err_new.value tox_err_new = tox_err_new.value
if tox_err_new == TOX_ERR_NEW['NULL']: if tox_err_new == TOX_ERR_NEW['NULL']:
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.') raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
@ -138,7 +138,7 @@ class Tox(object):
tox_err_options_new = c_int() tox_err_options_new = c_int()
f = Tox.libtoxcore.tox_options_new f = Tox.libtoxcore.tox_options_new
f.restype = POINTER(ToxOptions) f.restype = POINTER(ToxOptions)
result = f(addressof(tox_err_options_new)) result = f(byref(tox_err_options_new))
tox_err_options_new = tox_err_options_new.value tox_err_options_new = tox_err_options_new.value
if tox_err_options_new == TOX_ERR_OPTIONS_NEW['OK']: if tox_err_options_new == TOX_ERR_OPTIONS_NEW['OK']:
return result return result
@ -202,7 +202,7 @@ class Tox(object):
""" """
tox_err_bootstrap = c_int() tox_err_bootstrap = c_int()
result = Tox.libtoxcore.tox_bootstrap(self._tox_pointer, c_char_p(address), c_uint16(port), result = Tox.libtoxcore.tox_bootstrap(self._tox_pointer, c_char_p(address), c_uint16(port),
string_to_bin(public_key), addressof(tox_err_bootstrap)) string_to_bin(public_key), byref(tox_err_bootstrap))
tox_err_bootstrap = tox_err_bootstrap.value tox_err_bootstrap = tox_err_bootstrap.value
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']: if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
return bool(result) return bool(result)
@ -228,7 +228,7 @@ class Tox(object):
""" """
tox_err_bootstrap = c_int() tox_err_bootstrap = c_int()
result = Tox.libtoxcore.tox_add_tcp_relay(self._tox_pointer, c_char_p(address), c_uint16(port), result = Tox.libtoxcore.tox_add_tcp_relay(self._tox_pointer, c_char_p(address), c_uint16(port),
c_char_p(public_key), addressof(tox_err_bootstrap)) c_char_p(public_key), byref(tox_err_bootstrap))
tox_err_bootstrap = tox_err_bootstrap.value tox_err_bootstrap = tox_err_bootstrap.value
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']: if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
return bool(result) return bool(result)
@ -355,7 +355,7 @@ class Tox(object):
""" """
tox_err_set_info = c_int() tox_err_set_info = c_int()
result = Tox.libtoxcore.tox_self_set_name(self._tox_pointer, c_char_p(name), result = Tox.libtoxcore.tox_self_set_name(self._tox_pointer, c_char_p(name),
c_size_t(len(name)), addressof(tox_err_set_info)) c_size_t(len(name)), byref(tox_err_set_info))
tox_err_set_info = tox_err_set_info.value tox_err_set_info = tox_err_set_info.value
if tox_err_set_info == TOX_ERR_SET_INFO['OK']: if tox_err_set_info == TOX_ERR_SET_INFO['OK']:
return bool(result) return bool(result)
@ -403,7 +403,7 @@ class Tox(object):
""" """
tox_err_set_info = c_int() tox_err_set_info = c_int()
result = Tox.libtoxcore.tox_self_set_status_message(self._tox_pointer, c_char_p(status_message), result = Tox.libtoxcore.tox_self_set_status_message(self._tox_pointer, c_char_p(status_message),
c_size_t(len(status_message)), addressof(tox_err_set_info)) c_size_t(len(status_message)), byref(tox_err_set_info))
tox_err_set_info = tox_err_set_info.value tox_err_set_info = tox_err_set_info.value
if tox_err_set_info == TOX_ERR_SET_INFO['OK']: if tox_err_set_info == TOX_ERR_SET_INFO['OK']:
return bool(result) return bool(result)
@ -479,7 +479,7 @@ class Tox(object):
""" """
tox_err_friend_add = c_int() tox_err_friend_add = c_int()
result = Tox.libtoxcore.tox_friend_add(self._tox_pointer, string_to_bin(address), c_char_p(message), result = Tox.libtoxcore.tox_friend_add(self._tox_pointer, string_to_bin(address), c_char_p(message),
c_size_t(len(message)), addressof(tox_err_friend_add)) c_size_t(len(message)), byref(tox_err_friend_add))
tox_err_friend_add = tox_err_friend_add.value tox_err_friend_add = tox_err_friend_add.value
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']: if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']:
return result return result
@ -519,7 +519,7 @@ class Tox(object):
""" """
tox_err_friend_add = c_int() tox_err_friend_add = c_int()
result = Tox.libtoxcore.tox_friend_add_norequest(self._tox_pointer, string_to_bin(public_key), result = Tox.libtoxcore.tox_friend_add_norequest(self._tox_pointer, string_to_bin(public_key),
addressof(tox_err_friend_add)) byref(tox_err_friend_add))
tox_err_friend_add = tox_err_friend_add.value tox_err_friend_add = tox_err_friend_add.value
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']: if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']:
return result return result
@ -554,7 +554,7 @@ class Tox(object):
""" """
tox_err_friend_delete = c_int() tox_err_friend_delete = c_int()
result = Tox.libtoxcore.tox_friend_delete(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_delete(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_delete)) byref(tox_err_friend_delete))
tox_err_friend_delete = tox_err_friend_delete.value tox_err_friend_delete = tox_err_friend_delete.value
if tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['OK']: if tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['OK']:
return bool(result) return bool(result)
@ -574,7 +574,7 @@ class Tox(object):
""" """
tox_err_friend_by_public_key = c_int() tox_err_friend_by_public_key = c_int()
result = Tox.libtoxcore.tox_friend_by_public_key(self._tox_pointer, string_to_bin(public_key), result = Tox.libtoxcore.tox_friend_by_public_key(self._tox_pointer, string_to_bin(public_key),
addressof(tox_err_friend_by_public_key)) byref(tox_err_friend_by_public_key))
tox_err_friend_by_public_key = tox_err_friend_by_public_key.value tox_err_friend_by_public_key = tox_err_friend_by_public_key.value
if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['OK']: if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['OK']:
return result return result
@ -629,7 +629,7 @@ class Tox(object):
public_key = create_string_buffer(TOX_PUBLIC_KEY_SIZE) public_key = create_string_buffer(TOX_PUBLIC_KEY_SIZE)
tox_err_friend_get_public_key = c_int() tox_err_friend_get_public_key = c_int()
Tox.libtoxcore.tox_friend_get_public_key(self._tox_pointer, c_uint32(friend_number), public_key, Tox.libtoxcore.tox_friend_get_public_key(self._tox_pointer, c_uint32(friend_number), public_key,
addressof(tox_err_friend_get_public_key)) byref(tox_err_friend_get_public_key))
tox_err_friend_get_public_key = tox_err_friend_get_public_key.value tox_err_friend_get_public_key = tox_err_friend_get_public_key.value
if tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['OK']: if tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['OK']:
return bin_to_string(public_key, TOX_PUBLIC_KEY_SIZE) return bin_to_string(public_key, TOX_PUBLIC_KEY_SIZE)
@ -646,7 +646,7 @@ class Tox(object):
""" """
tox_err_last_online = c_int() tox_err_last_online = c_int()
result = Tox.libtoxcore.tox_friend_get_last_online(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_last_online(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_last_online)) byref(tox_err_last_online))
tox_err_last_online = tox_err_last_online.value tox_err_last_online = tox_err_last_online.value
if tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['OK']: if tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['OK']:
return result return result
@ -665,7 +665,7 @@ class Tox(object):
""" """
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
result = Tox.libtoxcore.tox_friend_get_name_size(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_name_size(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return result return result
@ -691,7 +691,7 @@ class Tox(object):
name = create_string_buffer(self.friend_get_name_size(friend_number)) name = create_string_buffer(self.friend_get_name_size(friend_number))
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
Tox.libtoxcore.tox_friend_get_name(self._tox_pointer, c_uint32(friend_number), name, Tox.libtoxcore.tox_friend_get_name(self._tox_pointer, c_uint32(friend_number), name,
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return name.value.decode('utf8') return name.value.decode('utf8')
@ -727,7 +727,7 @@ class Tox(object):
""" """
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
result = Tox.libtoxcore.tox_friend_get_status_message_size(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_status_message_size(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return result return result
@ -755,7 +755,7 @@ class Tox(object):
status_message = create_string_buffer(self.friend_get_status_message_size(friend_number)) status_message = create_string_buffer(self.friend_get_status_message_size(friend_number))
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
Tox.libtoxcore.tox_friend_get_status_message(self._tox_pointer, c_uint32(friend_number), status_message, Tox.libtoxcore.tox_friend_get_status_message(self._tox_pointer, c_uint32(friend_number), status_message,
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return status_message.value.decode('utf8') return status_message.value.decode('utf8')
@ -796,7 +796,7 @@ class Tox(object):
""" """
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
result = Tox.libtoxcore.tox_friend_get_status(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_status(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return result return result
@ -835,7 +835,7 @@ class Tox(object):
""" """
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
result = Tox.libtoxcore.tox_friend_get_connection_status(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_connection_status(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return result return result
@ -875,7 +875,7 @@ class Tox(object):
""" """
tox_err_friend_query = c_int() tox_err_friend_query = c_int()
result = Tox.libtoxcore.tox_friend_get_typing(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_get_typing(self._tox_pointer, c_uint32(friend_number),
addressof(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
return bool(result) return bool(result)
@ -918,7 +918,7 @@ class Tox(object):
""" """
tox_err_set_typing = c_int() tox_err_set_typing = c_int()
result = Tox.libtoxcore.tox_self_set_typing(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_self_set_typing(self._tox_pointer, c_uint32(friend_number),
c_bool(typing), addressof(tox_err_set_typing)) c_bool(typing), byref(tox_err_set_typing))
tox_err_set_typing = tox_err_set_typing.value tox_err_set_typing = tox_err_set_typing.value
if tox_err_set_typing == TOX_ERR_SET_TYPING['OK']: if tox_err_set_typing == TOX_ERR_SET_TYPING['OK']:
return bool(result) return bool(result)
@ -948,7 +948,7 @@ class Tox(object):
tox_err_friend_send_message = c_int() tox_err_friend_send_message = c_int()
result = Tox.libtoxcore.tox_friend_send_message(self._tox_pointer, c_uint32(friend_number), result = Tox.libtoxcore.tox_friend_send_message(self._tox_pointer, c_uint32(friend_number),
c_int(message_type), c_char_p(message), c_size_t(len(message)), c_int(message_type), c_char_p(message), c_size_t(len(message)),
addressof(tox_err_friend_send_message)) byref(tox_err_friend_send_message))
tox_err_friend_send_message = tox_err_friend_send_message.value tox_err_friend_send_message = tox_err_friend_send_message.value
if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['OK']: if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['OK']:
return result return result
@ -1058,7 +1058,7 @@ class Tox(object):
""" """
tox_err_file_control = c_int() tox_err_file_control = c_int()
result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number), result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
c_int(control), addressof(tox_err_file_control)) c_int(control), byref(tox_err_file_control))
tox_err_file_control = tox_err_file_control.value tox_err_file_control = tox_err_file_control.value
if tox_err_file_control == TOX_ERR_FILE_CONTROL['OK']: if tox_err_file_control == TOX_ERR_FILE_CONTROL['OK']:
return bool(result) return bool(result)
@ -1113,7 +1113,7 @@ class Tox(object):
""" """
tox_err_file_seek = c_int() tox_err_file_seek = c_int()
result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number), result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
c_uint64(position), addressof(tox_err_file_seek)) c_uint64(position), byref(tox_err_file_seek))
tox_err_file_seek = tox_err_file_seek.value tox_err_file_seek = tox_err_file_seek.value
if tox_err_file_seek == TOX_ERR_FILE_SEEK['OK']: if tox_err_file_seek == TOX_ERR_FILE_SEEK['OK']:
return bool(result) return bool(result)
@ -1143,8 +1143,8 @@ class Tox(object):
if file_id is None: if file_id is None:
file_id = create_string_buffer(TOX_FILE_ID_LENGTH) file_id = create_string_buffer(TOX_FILE_ID_LENGTH)
tox_err_file_get = c_int() tox_err_file_get = c_int()
Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number), file_id, Tox.libtoxcore.tox_get_file_id(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number), file_id,
addressof(tox_err_file_get)) byref(tox_err_file_get))
tox_err_file_get = tox_err_file_get.value tox_err_file_get = tox_err_file_get.value
if tox_err_file_get == TOX_ERR_FILE_GET['OK']: if tox_err_file_get == TOX_ERR_FILE_GET['OK']:
return bin_to_string(file_id, TOX_FILE_ID_LENGTH) return bin_to_string(file_id, TOX_FILE_ID_LENGTH)
@ -1207,7 +1207,7 @@ class Tox(object):
tox_err_file_send = c_int() tox_err_file_send = c_int()
result = self.libtoxcore.tox_file_send(self._tox_pointer, c_uint32(friend_number), c_uint32(kind), result = self.libtoxcore.tox_file_send(self._tox_pointer, c_uint32(friend_number), c_uint32(kind),
c_uint64(file_size), string_to_bin(file_id), c_char_p(filename), c_uint64(file_size), string_to_bin(file_id), c_char_p(filename),
c_size_t(len(filename)), addressof(tox_err_file_send)) c_size_t(len(filename)), byref(tox_err_file_send))
tox_err_file_send = tox_err_file_send.value tox_err_file_send = tox_err_file_send.value
if tox_err_file_send == TOX_ERR_FILE_SEND['OK']: if tox_err_file_send == TOX_ERR_FILE_SEND['OK']:
return result return result
@ -1242,7 +1242,7 @@ class Tox(object):
tox_err_file_send_chunk = c_int() tox_err_file_send_chunk = c_int()
result = self.libtoxcore.tox_file_send_chunk(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number), result = self.libtoxcore.tox_file_send_chunk(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
c_uint64(position), c_char_p(data), c_size_t(len(data)), c_uint64(position), c_char_p(data), c_size_t(len(data)),
addressof(tox_err_file_send_chunk)) byref(tox_err_file_send_chunk))
tox_err_file_send_chunk = tox_err_file_send_chunk.value tox_err_file_send_chunk = tox_err_file_send_chunk.value
if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['OK']: if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['OK']:
return bool(result) return bool(result)
@ -1383,7 +1383,7 @@ class Tox(object):
Return the UDP port this Tox instance is bound to. Return the UDP port this Tox instance is bound to.
""" """
tox_err_get_port = c_int() tox_err_get_port = c_int()
result = Tox.libtoxcore.tox_self_get_udp_port(self._tox_pointer, addressof(tox_err_get_port)) result = Tox.libtoxcore.tox_self_get_udp_port(self._tox_pointer, byref(tox_err_get_port))
tox_err_get_port = tox_err_get_port.value tox_err_get_port = tox_err_get_port.value
if tox_err_get_port == TOX_ERR_GET_PORT['OK']: if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
return result return result
@ -1396,17 +1396,9 @@ class Tox(object):
relay. relay.
""" """
tox_err_get_port = c_int() tox_err_get_port = c_int()
result = Tox.libtoxcore.tox_self_get_tcp_port(self._tox_pointer, addressof(tox_err_get_port)) result = Tox.libtoxcore.tox_self_get_tcp_port(self._tox_pointer, byref(tox_err_get_port))
tox_err_get_port = tox_err_get_port.value tox_err_get_port = tox_err_get_port.value
if tox_err_get_port == TOX_ERR_GET_PORT['OK']: if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
return result return result
elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
raise RuntimeError('The instance was not bound to any port.') raise RuntimeError('The instance was not bound to any port.')
if __name__ == '__main__':
tox = Tox(Tox.options_new())
p = tox.get_savedata()
print type(p)
print p
del tox

13
util.py
View File

@ -1,3 +1,5 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import os import os
@ -10,11 +12,20 @@ def curr_directory():
return os.path.dirname(os.path.realpath(__file__)) return os.path.dirname(os.path.realpath(__file__))
def folder_size(path):
size = 0
for f in os.listdir(path):
f = unicode(f)
if os.path.isfile(os.path.join(path, f)):
size += os.path.getsize(os.path.join(path, f))
return size
class Singleton(object): class Singleton(object):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'): if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance return cls._instance
@classmethod @classmethod