2014-05-04 17:26:43 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
2014-09-02 22:32:44 +00:00
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
|
|
|
from copy import deepcopy
|
2014-05-17 00:14:15 +00:00
|
|
|
import json
|
2014-08-12 08:16:57 +00:00
|
|
|
import os
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-05-25 18:06:12 +00:00
|
|
|
import ox
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-08-12 08:16:57 +00:00
|
|
|
from changelog import Changelog
|
|
|
|
from oxtornado import actions
|
2014-05-18 23:24:04 +00:00
|
|
|
from utils import update_dict
|
2014-09-02 22:32:44 +00:00
|
|
|
from . import models
|
2014-05-04 17:26:43 +00:00
|
|
|
import settings
|
|
|
|
import state
|
2016-01-16 13:11:20 +00:00
|
|
|
import tor_request
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-05-17 14:26:59 +00:00
|
|
|
import logging
|
2015-11-29 14:56:38 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2014-05-17 14:26:59 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def init(data):
|
2014-05-04 17:26:43 +00:00
|
|
|
'''
|
2014-05-18 23:24:04 +00:00
|
|
|
takes {
|
|
|
|
}
|
|
|
|
returns {
|
|
|
|
config
|
|
|
|
user
|
|
|
|
preferences
|
|
|
|
ui
|
|
|
|
}
|
2014-05-04 17:26:43 +00:00
|
|
|
'''
|
|
|
|
response = {}
|
|
|
|
if os.path.exists(settings.oml_config_path):
|
|
|
|
with open(settings.oml_config_path) as fd:
|
|
|
|
config = json.load(fd)
|
|
|
|
else:
|
|
|
|
config = {}
|
|
|
|
response['config'] = config
|
|
|
|
response['user'] = deepcopy(config['user'])
|
2016-01-10 13:53:29 +00:00
|
|
|
response['version'] = settings.MINOR_VERSION
|
2014-05-04 17:26:43 +00:00
|
|
|
if settings.preferences:
|
|
|
|
response['user']['preferences'] = settings.preferences
|
|
|
|
response['user']['id'] = settings.USER_ID
|
|
|
|
response['user']['online'] = state.online
|
|
|
|
if settings.ui:
|
2016-01-13 16:39:25 +00:00
|
|
|
for f in settings.ui['filters']:
|
|
|
|
if f['id'] == 'classification':
|
|
|
|
f['id'] = 'categories'
|
|
|
|
settings.ui._save()
|
2014-05-04 17:26:43 +00:00
|
|
|
response['user']['ui'] = settings.ui
|
|
|
|
return response
|
|
|
|
actions.register(init)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def setPreferences(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
key: value,
|
|
|
|
'sub.key': value
|
|
|
|
}
|
|
|
|
'''
|
2014-05-04 17:26:43 +00:00
|
|
|
update_dict(settings.preferences, data)
|
2014-05-25 12:16:04 +00:00
|
|
|
if 'username' in data:
|
|
|
|
u = state.user()
|
|
|
|
u.update_name()
|
|
|
|
u.save()
|
2014-05-04 17:26:43 +00:00
|
|
|
return settings.preferences
|
|
|
|
actions.register(setPreferences)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def setUI(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
key: value,
|
|
|
|
'sub.key': value
|
|
|
|
}
|
|
|
|
'''
|
2014-05-04 17:26:43 +00:00
|
|
|
update_dict(settings.ui, data)
|
|
|
|
return settings.ui
|
|
|
|
actions.register(setUI)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def getUsers(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
returns {
|
|
|
|
users: []
|
|
|
|
}
|
|
|
|
'''
|
2014-05-04 17:26:43 +00:00
|
|
|
users = []
|
2015-11-29 15:39:26 +00:00
|
|
|
ids = set()
|
2014-05-04 17:26:43 +00:00
|
|
|
for u in models.User.query.filter(models.User.id!=settings.USER_ID).all():
|
|
|
|
users.append(u.json())
|
2015-11-29 15:39:26 +00:00
|
|
|
ids.add(u.id)
|
2016-01-05 17:52:17 +00:00
|
|
|
if state.nodes:
|
|
|
|
for id in state.nodes._local._nodes:
|
|
|
|
if id not in ids:
|
|
|
|
n = state.nodes._local._nodes[id].copy()
|
|
|
|
n['online'] = True
|
|
|
|
n['name'] = n['username']
|
|
|
|
users.append(n)
|
2014-05-25 18:06:12 +00:00
|
|
|
users.sort(key=lambda u: ox.sort_string(str(u.get('index', '')) + 'Z' + (u.get('name') or '')))
|
2014-05-04 17:26:43 +00:00
|
|
|
return {
|
|
|
|
"users": users
|
|
|
|
}
|
|
|
|
actions.register(getUsers)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def getLists(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
returns {
|
|
|
|
lists: []
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
from item.models import Item
|
2014-05-12 12:57:47 +00:00
|
|
|
lists = []
|
2014-05-18 23:24:04 +00:00
|
|
|
lists.append({
|
|
|
|
'id': '',
|
|
|
|
'items': Item.query.count(),
|
|
|
|
'name': 'Libraries',
|
|
|
|
'type': 'libraries',
|
2014-05-25 12:16:04 +00:00
|
|
|
'user': None,
|
2014-05-18 23:24:04 +00:00
|
|
|
})
|
2014-05-04 17:26:43 +00:00
|
|
|
for u in models.User.query.filter((models.User.peered==True)|(models.User.id==settings.USER_ID)):
|
2014-05-12 12:57:47 +00:00
|
|
|
lists += u.lists_json()
|
2014-05-04 17:26:43 +00:00
|
|
|
return {
|
|
|
|
'lists': lists
|
|
|
|
}
|
|
|
|
actions.register(getLists)
|
|
|
|
|
2014-05-18 23:24:04 +00:00
|
|
|
def validate_query(query):
|
2014-05-25 20:08:44 +00:00
|
|
|
validate_conditions(query['conditions'])
|
|
|
|
|
|
|
|
def validate_conditions(conditions):
|
|
|
|
for c in conditions:
|
|
|
|
if 'conditions' in c:
|
|
|
|
if list(sorted(c.keys())) != ['conditions', 'operator']:
|
|
|
|
raise Exception('invalid query condition', c)
|
2016-01-07 06:55:09 +00:00
|
|
|
validate_conditions(c['conditions'])
|
2014-05-25 20:08:44 +00:00
|
|
|
else:
|
|
|
|
if list(sorted(c.keys())) != ['key', 'operator', 'value']:
|
|
|
|
raise Exception('invalid query condition', c)
|
|
|
|
if c['key'] == 'list' and ':' not in c['value']:
|
|
|
|
raise Exception('invalid query condition', c)
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def addList(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
name
|
|
|
|
items
|
|
|
|
query
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
logger.debug('addList %s', data)
|
2014-05-04 17:26:43 +00:00
|
|
|
user_id = settings.USER_ID
|
2014-05-18 23:24:04 +00:00
|
|
|
if 'query' in data:
|
|
|
|
validate_query(data['query'])
|
|
|
|
if data['name']:
|
2014-05-04 17:26:43 +00:00
|
|
|
l = models.List.create(user_id, data['name'], data.get('query'))
|
|
|
|
if 'items' in data:
|
|
|
|
l.add_items(data['items'])
|
|
|
|
return l.json()
|
2014-05-18 23:24:04 +00:00
|
|
|
else:
|
|
|
|
raise Exception('name not set')
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(addList, cache=False)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def editList(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
name
|
|
|
|
query
|
|
|
|
}
|
|
|
|
'''
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('editList %s', data)
|
2014-05-04 17:26:43 +00:00
|
|
|
l = models.List.get_or_create(data['id'])
|
|
|
|
name = l.name
|
|
|
|
if 'name' in data:
|
|
|
|
l.name = data['name']
|
2014-05-25 20:08:44 +00:00
|
|
|
if 'query' in data and l.type != 'smart':
|
|
|
|
raise Exception('query only for smart lists')
|
|
|
|
if 'query' in data and l.type == 'smart':
|
2014-05-18 23:24:04 +00:00
|
|
|
validate_query(data['query'])
|
2014-05-04 17:26:43 +00:00
|
|
|
l._query = data['query']
|
|
|
|
if l.type == 'static' and name != l.name:
|
|
|
|
Changelog.record(state.user(), 'editlist', name, {'name': l.name})
|
|
|
|
l.save()
|
2014-05-17 14:26:59 +00:00
|
|
|
return l.json()
|
2014-05-04 17:26:43 +00:00
|
|
|
actions.register(editList, cache=False)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def removeList(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
l = models.List.get(data['id'])
|
|
|
|
if l:
|
|
|
|
l.remove()
|
|
|
|
return {}
|
|
|
|
actions.register(removeList, cache=False)
|
|
|
|
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
def addListItems(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
list
|
|
|
|
items
|
|
|
|
}
|
|
|
|
'''
|
2014-05-17 23:14:29 +00:00
|
|
|
if data['list'] == ':':
|
|
|
|
from item.models import Item
|
|
|
|
for item_id in data['items']:
|
|
|
|
i = Item.get(item_id)
|
2014-05-21 00:02:21 +00:00
|
|
|
i.queue_download()
|
|
|
|
i.update()
|
2014-05-17 23:14:29 +00:00
|
|
|
elif data['list']:
|
|
|
|
l = models.List.get_or_create(data['list'])
|
|
|
|
if l:
|
|
|
|
l.add_items(data['items'])
|
|
|
|
return l.json()
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
2014-05-12 12:57:47 +00:00
|
|
|
actions.register(addListItems, cache=False)
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def removeListItems(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
list
|
|
|
|
items
|
|
|
|
}
|
|
|
|
'''
|
2014-05-12 12:57:47 +00:00
|
|
|
l = models.List.get(data['list'])
|
|
|
|
if l:
|
|
|
|
l.remove_items(data['items'])
|
|
|
|
return l.json()
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
2014-05-12 12:57:47 +00:00
|
|
|
actions.register(removeListItems, cache=False)
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def sortLists(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
ids
|
|
|
|
}
|
|
|
|
'''
|
2014-05-04 17:26:43 +00:00
|
|
|
n = 0
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('sortLists %s', data)
|
2014-05-25 18:06:12 +00:00
|
|
|
lists = []
|
2014-05-04 17:26:43 +00:00
|
|
|
for id in data['ids']:
|
|
|
|
l = models.List.get(id)
|
2014-05-25 18:06:12 +00:00
|
|
|
l.index_ = n
|
2014-05-04 17:26:43 +00:00
|
|
|
n += 1
|
2014-05-25 18:06:12 +00:00
|
|
|
if l.type == 'static':
|
|
|
|
lists.append(l.name)
|
2014-08-09 16:14:14 +00:00
|
|
|
state.db.session.add(l)
|
|
|
|
state.db.session.commit()
|
2014-05-25 18:06:12 +00:00
|
|
|
if lists:
|
|
|
|
Changelog.record(state.user(), 'orderlists', lists)
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(sortLists, cache=False)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def editUser(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
nickname
|
|
|
|
}
|
|
|
|
'''
|
2014-05-04 17:26:43 +00:00
|
|
|
if 'nickname' in data:
|
|
|
|
p = models.User.get_or_create(data['id'])
|
2014-05-25 12:16:04 +00:00
|
|
|
if data['nickname']:
|
|
|
|
p.info['nickname'] = data['nickname']
|
|
|
|
elif 'nickname' in p.info:
|
|
|
|
del p.info['nickname']
|
2014-05-25 18:06:12 +00:00
|
|
|
old = p.nickname
|
2014-05-25 12:16:04 +00:00
|
|
|
p.update_name()
|
2014-05-25 18:06:12 +00:00
|
|
|
if old != p.nickname:
|
|
|
|
models.List.rename_user(old, p.nickname)
|
2014-05-04 17:26:43 +00:00
|
|
|
p.save()
|
2014-05-25 12:44:07 +00:00
|
|
|
return p.json()
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(editUser, cache=False)
|
|
|
|
|
2014-05-25 18:06:12 +00:00
|
|
|
def sortUsers(data):
|
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
ids
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
n = 0
|
|
|
|
logger.debug('sortUsers %s', data)
|
|
|
|
for id in data['ids']:
|
|
|
|
u = models.User.get(id)
|
|
|
|
u.info['index'] = n
|
|
|
|
n += 1
|
2014-08-09 16:14:14 +00:00
|
|
|
state.db.session.add(u)
|
|
|
|
state.db.session.commit()
|
2014-05-25 18:06:12 +00:00
|
|
|
return {}
|
|
|
|
actions.register(sortUsers, cache=False)
|
2014-05-19 20:14:24 +00:00
|
|
|
|
2014-05-20 00:33:06 +00:00
|
|
|
def requestPeering(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
message
|
2015-02-26 10:52:40 +00:00
|
|
|
nickname (optional)
|
2014-05-18 23:24:04 +00:00
|
|
|
}
|
|
|
|
'''
|
2015-11-26 00:26:10 +00:00
|
|
|
if len(data.get('id', '')) != 16:
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('invalid user id')
|
2014-05-17 00:14:15 +00:00
|
|
|
return {}
|
2014-05-18 03:01:24 +00:00
|
|
|
u = models.User.get_or_create(data['id'])
|
|
|
|
u.pending = 'sent'
|
|
|
|
u.queued = True
|
|
|
|
u.info['message'] = data.get('message', '')
|
2015-02-26 10:52:40 +00:00
|
|
|
if data.get('nickname'):
|
|
|
|
u.info['nickname'] = data.get('nickname', '')
|
|
|
|
u.update_name()
|
2014-05-18 03:01:24 +00:00
|
|
|
u.save()
|
|
|
|
state.nodes.queue('add', u.id)
|
2014-05-20 00:33:06 +00:00
|
|
|
state.nodes.queue(u.id, 'peering', 'requestPeering')
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
2014-05-20 00:33:06 +00:00
|
|
|
actions.register(requestPeering, cache=False)
|
2014-05-19 20:14:24 +00:00
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
def acceptPeering(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
message
|
|
|
|
}
|
|
|
|
'''
|
2015-11-26 00:26:10 +00:00
|
|
|
if len(data.get('id', '')) != 16:
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('invalid user id')
|
2014-05-17 00:14:15 +00:00
|
|
|
return {}
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('acceptPeering... %s', data)
|
2014-05-18 03:01:24 +00:00
|
|
|
u = models.User.get_or_create(data['id'])
|
|
|
|
u.info['message'] = data.get('message', '')
|
|
|
|
u.update_peering(True)
|
|
|
|
state.nodes.queue('add', u.id)
|
|
|
|
state.nodes.queue(u.id, 'peering', 'acceptPeering')
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(acceptPeering, cache=False)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def rejectPeering(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
message
|
|
|
|
}
|
|
|
|
'''
|
2015-11-26 12:40:39 +00:00
|
|
|
if len(data.get('id', '')) not in (16, 43):
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('invalid user id')
|
2014-05-17 00:14:15 +00:00
|
|
|
return {}
|
2014-05-18 03:01:24 +00:00
|
|
|
u = models.User.get_or_create(data['id'])
|
|
|
|
u.info['message'] = data.get('message', '')
|
|
|
|
u.update_peering(False)
|
|
|
|
state.nodes.queue('add', u.id)
|
|
|
|
state.nodes.queue(u.id, 'peering', 'rejectPeering')
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(rejectPeering, cache=False)
|
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def removePeering(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
id
|
|
|
|
message
|
|
|
|
}
|
|
|
|
'''
|
2015-11-26 12:40:39 +00:00
|
|
|
if len(data.get('id', '')) not in (16, 43):
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('invalid user id')
|
2014-05-17 00:14:15 +00:00
|
|
|
return {}
|
2014-05-13 10:36:02 +00:00
|
|
|
u = models.User.get_or_create(data['id'])
|
2014-05-18 03:01:24 +00:00
|
|
|
u.info['message'] = data.get('message', '')
|
|
|
|
u.update_peering(False)
|
2014-05-13 10:36:02 +00:00
|
|
|
state.nodes.queue('add', u.id)
|
2014-05-18 03:01:24 +00:00
|
|
|
state.nodes.queue(u.id, 'peering', 'removePeering')
|
2014-05-04 17:26:43 +00:00
|
|
|
return {}
|
|
|
|
actions.register(removePeering, cache=False)
|
2014-05-12 23:43:27 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def cancelPeering(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
takes {
|
|
|
|
}
|
|
|
|
'''
|
2015-11-26 00:26:10 +00:00
|
|
|
if len(data.get('id', '')) != 16:
|
2014-05-17 14:26:59 +00:00
|
|
|
logger.debug('invalid user id')
|
2014-05-17 00:14:15 +00:00
|
|
|
return {}
|
2014-05-18 03:01:24 +00:00
|
|
|
u = models.User.get_or_create(data['id'])
|
|
|
|
u.info['message'] = data.get('message', '')
|
|
|
|
u.update_peering(False)
|
|
|
|
state.nodes.queue('add', u.id)
|
|
|
|
state.nodes.queue(u.id, 'peering', 'cancelPeering')
|
2014-05-12 23:43:27 +00:00
|
|
|
return {}
|
|
|
|
actions.register(cancelPeering, cache=False)
|
2014-05-17 00:14:15 +00:00
|
|
|
|
2014-05-19 20:14:24 +00:00
|
|
|
|
|
|
|
def getActivity(data):
|
2014-05-18 23:24:04 +00:00
|
|
|
'''
|
|
|
|
return {
|
|
|
|
activity
|
|
|
|
progress
|
|
|
|
}
|
|
|
|
'''
|
2014-05-17 00:14:15 +00:00
|
|
|
return state.activity
|
|
|
|
actions.register(getActivity, cache=False)
|
2016-01-16 13:11:20 +00:00
|
|
|
|
|
|
|
def contact(data):
|
|
|
|
'''
|
|
|
|
return {
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
response = {}
|
|
|
|
url = 'http://rnogx24drkbnrxa3.onion/contact'
|
|
|
|
headers = {
|
|
|
|
'User-Agent': settings.USER_AGENT,
|
|
|
|
}
|
|
|
|
try:
|
|
|
|
data = json.dumps(data).encode()
|
|
|
|
opener = tor_request.get_opener()
|
|
|
|
opener.addheaders = list(zip(headers.keys(), headers.values()))
|
|
|
|
r = opener.open(url, data)
|
|
|
|
error = r.status != 200
|
|
|
|
except:
|
|
|
|
logger.debug('failed to send contact', exc_info=True)
|
|
|
|
error = True
|
|
|
|
if error:
|
|
|
|
response = {'error': True}
|
|
|
|
return response
|
|
|
|
actions.register(contact, cache=False)
|