valar 1.1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of valar might be problematic. Click here for more details.
- channels/__init__.py +0 -0
- channels/consumer.py +48 -0
- channels/executer.py +13 -0
- channels/mapping.py +23 -0
- channels/sender.py +64 -0
- channels/views.py +12 -0
- classes/__init__.py +0 -0
- classes/auto_migration_mixin.py +7 -0
- classes/auto_urlpatterns_mixin.py +15 -0
- classes/counter.py +9 -0
- classes/singleton_meta.py +6 -0
- classes/valar_response.py +7 -0
- {valar-1.1.0.dist-info → valar-1.1.1.dist-info}/METADATA +1 -1
- valar-1.1.1.dist-info/RECORD +25 -0
- {valar-1.1.0.dist-info → valar-1.1.1.dist-info}/top_level.txt +3 -0
- views/__init__.py +0 -0
- valar-1.1.0.dist-info/RECORD +0 -12
- {valar-1.1.0.dist-info → valar-1.1.1.dist-info}/WHEEL +0 -0
- {valar-1.1.0.dist-info → valar-1.1.1.dist-info}/licenses/LICENSE +0 -0
channels/__init__.py
ADDED
|
File without changes
|
channels/consumer.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
|
3
|
+
|
|
4
|
+
VALAR_CHANNEL_GROUP = 'VALAR'
|
|
5
|
+
|
|
6
|
+
class ValarConsumer(AsyncJsonWebsocketConsumer):
|
|
7
|
+
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.client = None
|
|
10
|
+
self.uid = None
|
|
11
|
+
super().__init__()
|
|
12
|
+
|
|
13
|
+
async def connect(self):
|
|
14
|
+
params = self.scope['url_route']['kwargs']
|
|
15
|
+
self.client = params.get('client')
|
|
16
|
+
await self.channel_layer.group_add(VALAR_CHANNEL_GROUP, self.channel_name)
|
|
17
|
+
await self.accept()
|
|
18
|
+
|
|
19
|
+
async def disconnect(self, code):
|
|
20
|
+
await self.channel_layer.group_discard(VALAR_CHANNEL_GROUP, self.channel_name)
|
|
21
|
+
await self.close(code)
|
|
22
|
+
|
|
23
|
+
async def receive_json(self, data, *args, **kwargs):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
async def user_emit(self, event):
|
|
27
|
+
users: list = event.get('users',[])
|
|
28
|
+
data = event.get('data',{})
|
|
29
|
+
if self.uid in users:
|
|
30
|
+
await self.send_json(data)
|
|
31
|
+
|
|
32
|
+
async def client_emit(self, event):
|
|
33
|
+
clients: list = event.get('clients',[])
|
|
34
|
+
data = event.get('data',{})
|
|
35
|
+
if self.client in clients:
|
|
36
|
+
await self.send_json(data)
|
|
37
|
+
|
|
38
|
+
async def broadcast_emit(self, event):
|
|
39
|
+
data = event.get('data',{})
|
|
40
|
+
await self.send_json(data)
|
|
41
|
+
|
|
42
|
+
async def register_emit(self, event):
|
|
43
|
+
users: list = event.get('users', [])
|
|
44
|
+
clients: list = event.get('clients',[])
|
|
45
|
+
if self.client in clients:
|
|
46
|
+
self.uid = users[0]
|
|
47
|
+
|
|
48
|
+
|
channels/executer.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
async def execute_channel(method, sender):
|
|
4
|
+
thread = asyncio.to_thread(__execute__, method, sender)
|
|
5
|
+
asyncio.create_task(thread)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def __execute__(method, sender):
|
|
9
|
+
sender.to_clients(None, [sender.client], 'start')
|
|
10
|
+
method(sender)
|
|
11
|
+
sender.to_clients(None, [sender.client], 'stop')
|
|
12
|
+
|
|
13
|
+
|
channels/mapping.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
5
|
+
|
|
6
|
+
from ..classes.singleton_meta import SingletonMeta
|
|
7
|
+
|
|
8
|
+
class ChannelMapping(metaclass=SingletonMeta):
|
|
9
|
+
def __init__(self):
|
|
10
|
+
mapping = settings.HANDLER_MAPPING
|
|
11
|
+
root, name = mapping.rsplit('.', 1)
|
|
12
|
+
module = importlib.import_module(root)
|
|
13
|
+
if hasattr(module, name):
|
|
14
|
+
self.mapping: dict = getattr(module, name)
|
|
15
|
+
else:
|
|
16
|
+
raise ImproperlyConfigured("%r has no attribute %r" % (root, name))
|
|
17
|
+
|
|
18
|
+
def get_handler(self, handler):
|
|
19
|
+
method = self.mapping.get(handler)
|
|
20
|
+
if method is None:
|
|
21
|
+
raise ImproperlyConfigured("Cannot find handler - %r" % handler)
|
|
22
|
+
return method
|
|
23
|
+
|
channels/sender.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from asgiref.sync import async_to_sync
|
|
6
|
+
from channels.layers import get_channel_layer
|
|
7
|
+
from django.http import HttpRequest
|
|
8
|
+
|
|
9
|
+
from .consumer import VALAR_CHANNEL_GROUP
|
|
10
|
+
from ..classes.counter import Counter
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ValarSocketSender:
|
|
14
|
+
def __init__(self, request: HttpRequest, data=None):
|
|
15
|
+
body = json.loads(request.body)
|
|
16
|
+
auth = request.headers.get('AUTH')
|
|
17
|
+
self.client = request.headers.get('CLIENT')
|
|
18
|
+
self.uid = request.session.get('UID')
|
|
19
|
+
self.handlerKey = body.get('handlerKey')
|
|
20
|
+
self.channelKey = body.get('channelKey', 'default')
|
|
21
|
+
self.data = data or body.get('data')
|
|
22
|
+
self.send = get_channel_layer().group_send
|
|
23
|
+
self.start_time = time.time()
|
|
24
|
+
if auth and not self.uid:
|
|
25
|
+
raise Exception('Unauthorized!')
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def create_counter(length:int):
|
|
29
|
+
return Counter(length)
|
|
30
|
+
|
|
31
|
+
def __convert_body(self, emit, payload, status ,clients = None, users = None):
|
|
32
|
+
return {
|
|
33
|
+
'type': emit,
|
|
34
|
+
'data': {
|
|
35
|
+
'status': status,
|
|
36
|
+
'handlerKey': self.handlerKey,
|
|
37
|
+
'channelKey': self.channelKey,
|
|
38
|
+
'payload': payload,
|
|
39
|
+
'timestamp': datetime.now().timestamp()
|
|
40
|
+
},
|
|
41
|
+
'clients': clients or [],
|
|
42
|
+
'users': users or [],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def to_users(self, payload, users, status='proceed'):
|
|
47
|
+
body = self.__convert_body(emit='user.emit', payload=payload, status=status, users=users)
|
|
48
|
+
async_to_sync(self.send)(VALAR_CHANNEL_GROUP, body)
|
|
49
|
+
|
|
50
|
+
def to_clients(self,payload, clients, status='proceed', wait=False):
|
|
51
|
+
current_time = time.time()
|
|
52
|
+
time_span = current_time - self.start_time
|
|
53
|
+
if (wait and time_span > 1 and status == 'proceed') or not wait:
|
|
54
|
+
body = self.__convert_body(emit='client.emit', payload=payload, status=status, clients=clients)
|
|
55
|
+
async_to_sync(self.send)(VALAR_CHANNEL_GROUP, body)
|
|
56
|
+
self.start_time = current_time
|
|
57
|
+
|
|
58
|
+
def broadcast(self, payload, status):
|
|
59
|
+
body = self.__convert_body(emit='broadcast.emit', payload=payload, status=status)
|
|
60
|
+
async_to_sync(self.send)(VALAR_CHANNEL_GROUP, body)
|
|
61
|
+
|
|
62
|
+
def register(self):
|
|
63
|
+
body = self.__convert_body(emit='register.emit', payload=None, status=None,clients=[self.client], users=[self.uid])
|
|
64
|
+
async_to_sync(self.send)(VALAR_CHANNEL_GROUP, body)
|
channels/views.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
from .executer import execute_channel
|
|
3
|
+
from .mapping import ChannelMapping
|
|
4
|
+
from .sender import ValarSocketSender
|
|
5
|
+
from ..classes.valar_response import ValarResponse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def handel_channel(request, handler):
|
|
9
|
+
sender = ValarSocketSender(request)
|
|
10
|
+
method = ChannelMapping().get_handler(handler)
|
|
11
|
+
await execute_channel(method, sender)
|
|
12
|
+
return ValarResponse(True)
|
classes/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class AutoMigrationMixin:
|
|
2
|
+
name = None # 子类必须提供
|
|
3
|
+
def auto_migrate(self):
|
|
4
|
+
from django.core.management import call_command
|
|
5
|
+
call_command('makemigrations', self.name, interactive=False, verbosity=0)
|
|
6
|
+
call_command('migrate', self.name, interactive=False, verbosity=0)
|
|
7
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.urls import path, include
|
|
5
|
+
|
|
6
|
+
class AutoUrlPatternsMixin:
|
|
7
|
+
name = None # 子类必须提供
|
|
8
|
+
def set_url(self):
|
|
9
|
+
root = settings.ROOT_URLCONF
|
|
10
|
+
module = importlib.import_module(root)
|
|
11
|
+
urlpatterns: list = getattr(module, 'urlpatterns')
|
|
12
|
+
url = f'{self.name}.urls'
|
|
13
|
+
urlpatterns.append(path('data/', include(url)))
|
|
14
|
+
|
|
15
|
+
|
classes/counter.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class Counter:
|
|
2
|
+
def __init__(self, array_or_int):
|
|
3
|
+
self.length = array_or_int if isinstance(array_or_int,int) else len(array_or_int)
|
|
4
|
+
self.index = 0
|
|
5
|
+
|
|
6
|
+
def tick(self):
|
|
7
|
+
self.index += 1
|
|
8
|
+
percentage = round(self.index * 100 / self.length) if self.length else 0
|
|
9
|
+
return {"index": self.index, "length": self.length, "percentage": percentage}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
channels/consumer.py,sha256=w2Cc-4Jy3tt5h8lKwtmcsJd3yo6HOIrkPspDc1dIQSg,1421
|
|
3
|
+
channels/executer.py,sha256=lurFYyUETq6eWjFUXA-m7mmQTeZtwfxrzuOayWxs4BE,314
|
|
4
|
+
channels/mapping.py,sha256=1SBqxEYO4epbRkSOUw5zm6gau15imz1gokrRTQcy94A,755
|
|
5
|
+
channels/sender.py,sha256=x9oYOYSK0e5E37GauWF5KKbyG1toe8wRAPwSAv0TQms,2465
|
|
6
|
+
channels/views.py,sha256=SMY80ZVDDjIZI-k75TymhToV-3fXPAMxcD93G7mDeRw,374
|
|
7
|
+
classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
classes/auto_migration_mixin.py,sha256=DrcZX1xR_b7S6mxvzDMidvt9uOUvyUkONlc7Dqyci2w,306
|
|
9
|
+
classes/auto_urlpatterns_mixin.py,sha256=b0gB2_GpFfpLusNAFGrDvCxlSRghlNlRzNyadrtLDLo,414
|
|
10
|
+
classes/counter.py,sha256=K8aQUI1RiIrSOg3280tV102soC-ZC1qSRZvBXuwNYQ0,377
|
|
11
|
+
classes/singleton_meta.py,sha256=aa9DZKG4Q9Cr67ZWrQ0yaFLrEjwFoTMQbDrpoIqgJZs,245
|
|
12
|
+
classes/valar_response.py,sha256=kQnHWm8McUKTE_Q20JjLQsXOAv-IX979FRg6O42Tsng,246
|
|
13
|
+
frame/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
migrations/0001_initial.py,sha256=fW74vobQLZ-cJlljq7LnuxlbMb_qibtx6sVDl6Egrq8,9745
|
|
15
|
+
migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
models/__init__.py,sha256=t5BRtyeM8Pa3MRpiC72IoMIl6-2YGEZrU77iemLfuSk,31
|
|
17
|
+
models/core.py,sha256=a-EEN6-s_wdKrgw8nJTPvWcvxRiSG-ff7k_L5_crW-0,3439
|
|
18
|
+
models/frame.py,sha256=MrgcPfBLN0nvpIm2gF68YjmavIgOMGLZUjJ-eiNb90o,1016
|
|
19
|
+
models/meta.py,sha256=auy7ofa5aR_1dmp-DtoQ7DiFsqKc923-Wh0ymTh7k0A,4470
|
|
20
|
+
valar-1.1.1.dist-info/licenses/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
|
21
|
+
views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
valar-1.1.1.dist-info/METADATA,sha256=aexsxxMh3lDjfb5DclyQti1LOiJHBq4PXxRjH8NE8Ho,3394
|
|
23
|
+
valar-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
valar-1.1.1.dist-info/top_level.txt,sha256=n9GN471ruasH7el7VNwZw38g_HywLvQO8AZEa90aWY8,47
|
|
25
|
+
valar-1.1.1.dist-info/RECORD,,
|
views/__init__.py
ADDED
|
File without changes
|
valar-1.1.0.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
frame/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
migrations/0001_initial.py,sha256=fW74vobQLZ-cJlljq7LnuxlbMb_qibtx6sVDl6Egrq8,9745
|
|
3
|
-
migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
models/__init__.py,sha256=t5BRtyeM8Pa3MRpiC72IoMIl6-2YGEZrU77iemLfuSk,31
|
|
5
|
-
models/core.py,sha256=a-EEN6-s_wdKrgw8nJTPvWcvxRiSG-ff7k_L5_crW-0,3439
|
|
6
|
-
models/frame.py,sha256=MrgcPfBLN0nvpIm2gF68YjmavIgOMGLZUjJ-eiNb90o,1016
|
|
7
|
-
models/meta.py,sha256=auy7ofa5aR_1dmp-DtoQ7DiFsqKc923-Wh0ymTh7k0A,4470
|
|
8
|
-
valar-1.1.0.dist-info/licenses/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
|
9
|
-
valar-1.1.0.dist-info/METADATA,sha256=1VudqlWI655yj_yGwO7Ap-AgyKxaZ_t9hsonBuMqZ_A,3394
|
|
10
|
-
valar-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
valar-1.1.0.dist-info/top_level.txt,sha256=ePTyujihr1SPrcV-yRJAGVq34JJTyn6MmqGGvHpIGOo,24
|
|
12
|
-
valar-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|