simo 2.7.15__py3-none-any.whl → 2.7.16__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 simo might be problematic. Click here for more details.
- simo/__pycache__/urls.cpython-312.pyc +0 -0
- simo/automation/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/automation/gateways.py +5 -2
- simo/core/migrations/0049_alter_gateway_type.py +18 -0
- simo/core/migrations/__pycache__/0049_alter_gateway_type.cpython-312.pyc +0 -0
- simo/generic/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/generic/__pycache__/forms.cpython-312.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/generic/controllers.py +10 -0
- simo/generic/forms.py +13 -10
- simo/generic/gateways.py +43 -43
- simo/multimedia/__pycache__/admin.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/auto_urls.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/models.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/views.cpython-312.pyc +0 -0
- simo/multimedia/admin.py +7 -7
- simo/multimedia/auto_urls.py +5 -2
- simo/multimedia/controllers.py +16 -12
- simo/multimedia/migrations/0006_remove_sound_length_sound_duration.py +22 -0
- simo/multimedia/migrations/__pycache__/0006_remove_sound_length_sound_duration.cpython-312.pyc +0 -0
- simo/multimedia/models.py +8 -4
- simo/multimedia/views.py +63 -1
- simo/urls.py +6 -2
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/METADATA +1 -1
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/RECORD +30 -26
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/LICENSE.md +0 -0
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/WHEEL +0 -0
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/entry_points.txt +0 -0
- {simo-2.7.15.dist-info → simo-2.7.16.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
simo/automation/gateways.py
CHANGED
|
@@ -240,14 +240,16 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
240
240
|
|
|
241
241
|
comp = Component.objects.filter(id=id).first()
|
|
242
242
|
if comp and comp.value == 'finished':
|
|
243
|
+
if process.is_alive():
|
|
244
|
+
process.kill()
|
|
243
245
|
self.running_scripts.pop(id)
|
|
244
246
|
continue
|
|
245
247
|
|
|
246
248
|
if process.is_alive():
|
|
247
249
|
if not comp and id not in self.terminating_scripts:
|
|
248
250
|
# script is deleted and was not properly called to stop
|
|
249
|
-
self.running_scripts.pop(id)
|
|
250
251
|
process.kill()
|
|
252
|
+
self.running_scripts.pop(id)
|
|
251
253
|
continue
|
|
252
254
|
else:
|
|
253
255
|
self.last_death = time.time()
|
|
@@ -261,7 +263,6 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
261
263
|
comp.value = 'error'
|
|
262
264
|
comp.save()
|
|
263
265
|
|
|
264
|
-
|
|
265
266
|
if self.last_death and time.time() - self.last_death < 5:
|
|
266
267
|
# give 10s air before we wake these dead scripts up!
|
|
267
268
|
return
|
|
@@ -349,6 +350,7 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
349
350
|
print("START SCRIPT %s" % str(component))
|
|
350
351
|
if component.id in self.running_scripts:
|
|
351
352
|
if component.value in ('finished', 'error', 'stopped'):
|
|
353
|
+
self.running_scripts[component.id].kill()
|
|
352
354
|
self.running_scripts.pop(component.id)
|
|
353
355
|
elif component.id not in self.terminating_scripts \
|
|
354
356
|
and self.running_scripts[component.id].is_alive():
|
|
@@ -356,6 +358,7 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
356
358
|
component.value = 'running'
|
|
357
359
|
component.save()
|
|
358
360
|
return
|
|
361
|
+
self.running_scripts[component.id].kill()
|
|
359
362
|
|
|
360
363
|
self.running_scripts[component.id] = ScriptRunHandler(
|
|
361
364
|
component.id, multiprocessing.Event(),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-12-22 07:42
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('core', '0048_publicfile_privatefile'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='gateway',
|
|
15
|
+
name='type',
|
|
16
|
+
field=models.CharField(choices=[('simo.automation.gateways.AutomationsGatewayHandler', 'Automation'), ('simo_heos.gateways.HEOSGatewayHandler', 'DENON HEOS'), ('simo.generic.gateways.DummyGatewayHandler', 'Dummy'), ('simo.generic.gateways.GenericGatewayHandler', 'Generic'), ('simo_komfovent.gateways.KomfoventGatewayHandler', 'Komfovent'), ('simo.fleet.gateways.FleetGatewayHandler', 'SIMO.io Fleet')], db_index=True, max_length=200, unique=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/generic/controllers.py
CHANGED
|
@@ -1059,6 +1059,16 @@ class AudioAlert(Switch):
|
|
|
1059
1059
|
name = _("Audio Alert")
|
|
1060
1060
|
config_form = AudioAlertConfigForm
|
|
1061
1061
|
|
|
1062
|
+
def send(self, value):
|
|
1063
|
+
for player in Component.objects.filter(
|
|
1064
|
+
id__in=self.component.config['players']
|
|
1065
|
+
):
|
|
1066
|
+
if value:
|
|
1067
|
+
player.play_alert(self.component.id)
|
|
1068
|
+
else:
|
|
1069
|
+
self.component.set(False)
|
|
1070
|
+
player.cancel_alert()
|
|
1071
|
+
|
|
1062
1072
|
|
|
1063
1073
|
class StateSelect(ControllerBase):
|
|
1064
1074
|
gateway_class = GenericGatewayHandler
|
simo/generic/forms.py
CHANGED
|
@@ -7,7 +7,7 @@ from django.db.models import Q
|
|
|
7
7
|
from django.utils.translation import gettext_lazy as _
|
|
8
8
|
from django.core.files.uploadedfile import InMemoryUploadedFile
|
|
9
9
|
from simo.core.forms import HiddenField, BaseComponentForm
|
|
10
|
-
from simo.core.models import
|
|
10
|
+
from simo.core.models import Component
|
|
11
11
|
from simo.core.controllers import (
|
|
12
12
|
NumericSensor, MultiSensor, Switch, Dimmer
|
|
13
13
|
)
|
|
@@ -22,6 +22,7 @@ from simo.core.form_fields import (
|
|
|
22
22
|
)
|
|
23
23
|
from simo.core.forms import DimmerConfigForm, SwitchForm
|
|
24
24
|
from simo.core.form_fields import SoundField
|
|
25
|
+
from simo.multimedia.models import Sound
|
|
25
26
|
|
|
26
27
|
ACTION_METHODS = (
|
|
27
28
|
('turn_on', "Turn ON"), ('turn_off', "Turn OFF"),
|
|
@@ -670,24 +671,26 @@ class AudioAlertConfigForm(BaseComponentForm):
|
|
|
670
671
|
|
|
671
672
|
return self.cleaned_data['sound']
|
|
672
673
|
|
|
673
|
-
|
|
674
674
|
def save(self, commit=True):
|
|
675
675
|
obj = super().save(commit=commit)
|
|
676
676
|
if type(self.cleaned_data['sound']) != InMemoryUploadedFile:
|
|
677
677
|
return obj
|
|
678
678
|
|
|
679
|
-
|
|
680
|
-
|
|
679
|
+
sound = Sound(
|
|
680
|
+
name=self.cleaned_data['sound'].name,
|
|
681
|
+
duration=self.cleaned_data['sound'].duration
|
|
682
|
+
)
|
|
683
|
+
sound.file.save(
|
|
681
684
|
self.cleaned_data['sound'].name, self.cleaned_data['sound'],
|
|
682
685
|
save=True
|
|
683
686
|
)
|
|
684
|
-
|
|
685
|
-
id=self.instance.config.get('
|
|
686
|
-
)
|
|
687
|
-
|
|
688
|
-
org.delete()
|
|
689
|
-
self.instance.config['public_file_id'] = public_file.id
|
|
687
|
+
Sound.objects.filter(
|
|
688
|
+
id=self.instance.config.get('sound_id', 0)
|
|
689
|
+
).delete()
|
|
690
|
+
self.instance.config['sound_id'] = sound.id
|
|
690
691
|
self.instance.config['duration'] = self.cleaned_data['sound'].duration
|
|
692
|
+
self.instance.config['stream_url'] = sound.stream_url()
|
|
693
|
+
self.instance.config['file_url'] = sound.get_absolute_url()
|
|
691
694
|
self.instance.config['sound'] = self.cleaned_data['sound'].name
|
|
692
695
|
self.instance.save()
|
|
693
696
|
return obj
|
simo/generic/gateways.py
CHANGED
|
@@ -130,49 +130,49 @@ class GroupButtonsHandler:
|
|
|
130
130
|
group.toggle()
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
class AudioAlertsHandler:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
133
|
+
# class AudioAlertsHandler:
|
|
134
|
+
#
|
|
135
|
+
# def control_audio_alert(self, component, val):
|
|
136
|
+
# if val:
|
|
137
|
+
# public_file = PublicFile.objects.filter(
|
|
138
|
+
# component=component
|
|
139
|
+
# ).first()
|
|
140
|
+
# if not public_file:
|
|
141
|
+
# return
|
|
142
|
+
# uri = f"http://{get_self_ip()}{public_file.get_absolute_url()}"
|
|
143
|
+
# loop = component.config.get('loop', False)
|
|
144
|
+
# for pl_id in component.config.get('players', []):
|
|
145
|
+
# player = Component.objects.filter(
|
|
146
|
+
# id=pl_id, base_type='audio-player'
|
|
147
|
+
# ).first()
|
|
148
|
+
# if not player:
|
|
149
|
+
# continue
|
|
150
|
+
# player.play_alert(
|
|
151
|
+
# uri,
|
|
152
|
+
# component.config.get('loop', False),
|
|
153
|
+
# component.config.get('volume', 50)
|
|
154
|
+
# )
|
|
155
|
+
# if not loop:
|
|
156
|
+
# def set_done(comp):
|
|
157
|
+
# comp.set(False)
|
|
158
|
+
# threading.Timer(
|
|
159
|
+
# component.config.get('duration', 1),
|
|
160
|
+
# set_done, args=[component]
|
|
161
|
+
# )
|
|
162
|
+
# component.set(True)
|
|
163
|
+
# else:
|
|
164
|
+
# for pl_id in component.config.get('players', []):
|
|
165
|
+
# player = Component.objects.filter(
|
|
166
|
+
# id=pl_id, base_type='audio-player'
|
|
167
|
+
# ).first()
|
|
168
|
+
# if not player:
|
|
169
|
+
# continue
|
|
170
|
+
# player.cancel_alert()
|
|
171
|
+
# component.set(False)
|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
class GenericGatewayHandler(
|
|
175
|
-
BaseObjectCommandsGatewayHandler, GroupButtonsHandler
|
|
175
|
+
BaseObjectCommandsGatewayHandler, GroupButtonsHandler
|
|
176
176
|
):
|
|
177
177
|
name = "Generic"
|
|
178
178
|
config_form = BaseGatewayForm
|
|
@@ -268,7 +268,7 @@ class GenericGatewayHandler(
|
|
|
268
268
|
|
|
269
269
|
def on_mqtt_message(self, client, userdata, msg):
|
|
270
270
|
print("Mqtt message: ", msg.payload)
|
|
271
|
-
from simo.generic.controllers import AlarmGroup
|
|
271
|
+
from simo.generic.controllers import AlarmGroup#, #AudioAlert
|
|
272
272
|
|
|
273
273
|
payload = json.loads(msg.payload)
|
|
274
274
|
drop_current_instance()
|
|
@@ -278,8 +278,8 @@ class GenericGatewayHandler(
|
|
|
278
278
|
try:
|
|
279
279
|
if component.controller_uid == AlarmGroup.uid:
|
|
280
280
|
self.control_alarm_group(component, payload.get('set_val'))
|
|
281
|
-
elif component.controller_uid == AudioAlert.uid:
|
|
282
|
-
|
|
281
|
+
# elif component.controller_uid == AudioAlert.uid:
|
|
282
|
+
# self.control_audio_alert(component, payload.get('set_val'))
|
|
283
283
|
else:
|
|
284
284
|
component.controller.set(payload.get('set_val'))
|
|
285
285
|
except Exception:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/multimedia/admin.py
CHANGED
|
@@ -7,23 +7,23 @@ from .forms import SoundModelForm
|
|
|
7
7
|
|
|
8
8
|
@admin.register(Sound)
|
|
9
9
|
class SoundAdmin(admin.ModelAdmin):
|
|
10
|
-
list_display = 'id', 'name', 'file', '
|
|
10
|
+
list_display = 'id', 'name', 'file', 'duration_display', 'date_uploaded'
|
|
11
11
|
search_fields = 'name', 'file'
|
|
12
12
|
list_display_links = 'id', 'name',
|
|
13
13
|
form = SoundModelForm
|
|
14
|
-
readonly_fields = '
|
|
14
|
+
readonly_fields = 'duration_display',
|
|
15
15
|
|
|
16
|
-
def
|
|
17
|
-
if obj and obj.
|
|
18
|
-
return str(timedelta(seconds=obj.
|
|
16
|
+
def duration_display(self, obj=None):
|
|
17
|
+
if obj and obj.duration != None:
|
|
18
|
+
return str(timedelta(seconds=obj.duration))
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
duration_display.short_description = 'duration'
|
|
21
21
|
|
|
22
22
|
def save_model(self, request, obj, form, change):
|
|
23
23
|
super().save_model(request, obj, form, change)
|
|
24
24
|
# need to keep it here as using admin interface skips post_save signals
|
|
25
25
|
try:
|
|
26
|
-
obj.
|
|
26
|
+
obj.duration = int(
|
|
27
27
|
librosa.core.get_duration(
|
|
28
28
|
sr=22050, filename=obj.file.path
|
|
29
29
|
)
|
simo/multimedia/auto_urls.py
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
from django.urls import path, re_path
|
|
2
|
-
from .views import SoundAutocomplete
|
|
2
|
+
from .views import SoundAutocomplete, sound_stream
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
urlpatterns = [
|
|
6
6
|
path(
|
|
7
|
-
'autocomplete-sound',
|
|
7
|
+
'autocomplete-sound/',
|
|
8
8
|
SoundAutocomplete.as_view(), name='autocomplete-sound'
|
|
9
|
+
),
|
|
10
|
+
path(
|
|
11
|
+
'sound-<int:sound_id>-stream/', sound_stream, name='sound-stream'
|
|
9
12
|
)
|
|
10
13
|
]
|
simo/multimedia/controllers.py
CHANGED
|
@@ -90,18 +90,22 @@ class BasePlayer(Switch):
|
|
|
90
90
|
assert 0 <= volume <= 100
|
|
91
91
|
self.send({"play_uri": uri, 'volume': volume})
|
|
92
92
|
|
|
93
|
-
def play_alert(self, val, loop=False, volume=None):
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
# def play_alert(self, val, loop=False, volume=None):
|
|
94
|
+
# '''
|
|
95
|
+
# Plays alert and goes back to whatever was playing initially
|
|
96
|
+
# :param val: uri
|
|
97
|
+
# :param loop: Repeat infinitely
|
|
98
|
+
# :param volume: volume at which to play
|
|
99
|
+
# :return:
|
|
100
|
+
# '''
|
|
101
|
+
# assert type(val) == str
|
|
102
|
+
# if volume:
|
|
103
|
+
# assert 0 <= volume <= 100
|
|
104
|
+
# self.send({"alert": val, 'loop': loop, 'volume': volume})
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def play_alert(self, id):
|
|
108
|
+
self.send({"alert": id})
|
|
105
109
|
|
|
106
110
|
def cancel_alert(self):
|
|
107
111
|
'''Cancel alert if it's currently playing'''
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-12-22 07:42
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('multimedia', '0005_remove_sound_slug_sound_date_uploaded'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.RemoveField(
|
|
14
|
+
model_name='sound',
|
|
15
|
+
name='length',
|
|
16
|
+
),
|
|
17
|
+
migrations.AddField(
|
|
18
|
+
model_name='sound',
|
|
19
|
+
name='duration',
|
|
20
|
+
field=models.PositiveIntegerField(default=0, editable=False, help_text='Sound duration in seconds'),
|
|
21
|
+
),
|
|
22
|
+
]
|
simo/multimedia/migrations/__pycache__/0006_remove_sound_length_sound_duration.cpython-312.pyc
ADDED
|
Binary file
|
simo/multimedia/models.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os, librosa
|
|
2
|
+
from django.urls import reverse
|
|
2
3
|
from django.db import models
|
|
3
4
|
from django.db.models.signals import post_save, post_delete
|
|
4
5
|
from django.dispatch import receiver
|
|
@@ -15,8 +16,8 @@ class Sound(models.Model):
|
|
|
15
16
|
)
|
|
16
17
|
)
|
|
17
18
|
note = models.TextField(null=True, blank=True)
|
|
18
|
-
|
|
19
|
-
editable=False, default=0, help_text='Sound
|
|
19
|
+
duration = models.PositiveIntegerField(
|
|
20
|
+
editable=False, default=0, help_text='Sound duration in seconds'
|
|
20
21
|
)
|
|
21
22
|
date_uploaded = models.DateTimeField(auto_now_add=True)
|
|
22
23
|
|
|
@@ -26,11 +27,14 @@ class Sound(models.Model):
|
|
|
26
27
|
def get_absolute_url(self):
|
|
27
28
|
return self.file.url
|
|
28
29
|
|
|
30
|
+
def stream_url(self):
|
|
31
|
+
return reverse('sound-stream', kwargs={'sound_id': self.id})
|
|
32
|
+
|
|
29
33
|
|
|
30
34
|
@receiver(post_save, sender=Sound)
|
|
31
35
|
def determine_duration(sender, instance, created, **kwargs):
|
|
32
|
-
if not instance.
|
|
33
|
-
instance.
|
|
36
|
+
if not instance.duration:
|
|
37
|
+
instance.duration = int(
|
|
34
38
|
librosa.core.get_duration(
|
|
35
39
|
sr=22050, filename=instance.file.path
|
|
36
40
|
)
|
simo/multimedia/views.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import re, os
|
|
1
2
|
from django.http import Http404
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from wsgiref.util import FileWrapper
|
|
5
|
+
from django.shortcuts import get_object_or_404
|
|
6
|
+
from django.http import StreamingHttpResponse
|
|
2
7
|
from dal import autocomplete
|
|
3
8
|
from simo.core.utils.helpers import search_queryset
|
|
4
9
|
from .models import Sound
|
|
@@ -16,4 +21,61 @@ class SoundAutocomplete(autocomplete.Select2QuerySetView):
|
|
|
16
21
|
qs = qs.filter(pk__in=self.request.GET['value'].split(','))
|
|
17
22
|
elif self.q:
|
|
18
23
|
qs = search_queryset(qs, self.q, ('name', 'slug'))
|
|
19
|
-
return qs
|
|
24
|
+
return qs
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def file_iterator(file_path, chunk_size=8192, offset=0, length=None):
|
|
31
|
+
with open(file_path, "rb") as f:
|
|
32
|
+
f.seek(offset, os.SEEK_SET)
|
|
33
|
+
remaining = length
|
|
34
|
+
while True:
|
|
35
|
+
bytes_length = (
|
|
36
|
+
chunk_size
|
|
37
|
+
if remaining is None
|
|
38
|
+
else min(remaining, chunk_size)
|
|
39
|
+
)
|
|
40
|
+
data = f.read(bytes_length)
|
|
41
|
+
if not data:
|
|
42
|
+
break
|
|
43
|
+
if remaining:
|
|
44
|
+
remaining -= len(data)
|
|
45
|
+
yield data
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def sound_stream(request, sound_id):
|
|
50
|
+
sound = get_object_or_404(Sound, id=sound_id)
|
|
51
|
+
path = sound.file.path
|
|
52
|
+
content_type = "audio/" + path.split('.')[-1]
|
|
53
|
+
|
|
54
|
+
range_header = request.META.get("HTTP_RANGE", "").strip()
|
|
55
|
+
RANGE_RE = re.compile(r"bytes\s*=\s*(\d+)\s*-\s*(\d*)", re.I)
|
|
56
|
+
range_match = RANGE_RE.match(range_header)
|
|
57
|
+
size = os.path.getsize(path)
|
|
58
|
+
|
|
59
|
+
if range_match:
|
|
60
|
+
print(f"RANGE HEADER: {range_header}")
|
|
61
|
+
first_byte, last_byte = range_match.groups()
|
|
62
|
+
first_byte = int(first_byte) if first_byte else 0
|
|
63
|
+
last_byte = (
|
|
64
|
+
first_byte + 1024 * 1024 * 8
|
|
65
|
+
) # The max volume of the response body is 8M per piece
|
|
66
|
+
if last_byte >= size:
|
|
67
|
+
last_byte = size - 1
|
|
68
|
+
length = last_byte - first_byte + 1
|
|
69
|
+
response = StreamingHttpResponse(
|
|
70
|
+
file_iterator(path, offset=first_byte, length=length),
|
|
71
|
+
status=206,
|
|
72
|
+
content_type=content_type,
|
|
73
|
+
)
|
|
74
|
+
response["Content-Range"] = f"bytes {first_byte}-{last_byte}/{size}"
|
|
75
|
+
|
|
76
|
+
else:
|
|
77
|
+
response = StreamingHttpResponse(
|
|
78
|
+
FileWrapper(open(path, "rb")), content_type=content_type
|
|
79
|
+
)
|
|
80
|
+
response["Accept-Ranges"] = "bytes"
|
|
81
|
+
return response
|
simo/urls.py
CHANGED
|
@@ -55,10 +55,14 @@ for name, app in apps.app_configs.items():
|
|
|
55
55
|
'staticfiles'
|
|
56
56
|
):
|
|
57
57
|
continue
|
|
58
|
+
|
|
58
59
|
try:
|
|
59
60
|
urls = importlib.import_module('%s.auto_urls' % app.name)
|
|
60
|
-
except ModuleNotFoundError:
|
|
61
|
-
|
|
61
|
+
except ModuleNotFoundError as e:
|
|
62
|
+
if '%s.auto_urls' % app.name not in e.msg:
|
|
63
|
+
raise e
|
|
64
|
+
else:
|
|
65
|
+
continue
|
|
62
66
|
|
|
63
67
|
for var_name, item in urls.__dict__.items():
|
|
64
68
|
if isinstance(item, list) and var_name == 'urlpatterns':
|
|
@@ -3,7 +3,7 @@ simo/asgi.py,sha256=L8CUVZLM32IMzWDZ4IShdDN-m69t7oxAUeHods4-xNM,822
|
|
|
3
3
|
simo/celeryc.py,sha256=eab7_e9rw0c__DCeoUFUh_tjAGVlulxVrk75BaJf57Q,1512
|
|
4
4
|
simo/conf.py,sha256=H2BhXAV8MEDVXF8AbkaLSfR4ULd-9_bS4bnhE5sE5fg,112
|
|
5
5
|
simo/settings.py,sha256=CjHxwQvyljm0qVOCHvi6gdMweDzEqAedXTmGMJ6rE1A,7009
|
|
6
|
-
simo/urls.py,sha256=
|
|
6
|
+
simo/urls.py,sha256=d8g-wN0Xr2PVIV8RZl_h_PMN9KGZNIE9to2hQj1p1TU,2497
|
|
7
7
|
simo/__pycache__/__init__.cpython-312.pyc,sha256=a12_Zr7kC5DXzcFxA5eMu-TiSU5xbdF5cdKq-gwc3x0,159
|
|
8
8
|
simo/__pycache__/__init__.cpython-38.pyc,sha256=j81de0BqHMr6bs0C7cuYrXl7HwtK_vv8hDEtAdSwDJc,153
|
|
9
9
|
simo/__pycache__/asgi.cpython-312.pyc,sha256=3TFbweG4IzHv2br0bONji5wjd26pUvs1r_7fGXVBUVg,1263
|
|
@@ -14,14 +14,14 @@ simo/__pycache__/conf.cpython-312.pyc,sha256=q63YJWqaaaQLz3qXW8clENjvH1zUfY_k34_
|
|
|
14
14
|
simo/__pycache__/conf.cpython-38.pyc,sha256=MYP2yk3ULxiYwZsZR6tCLjKnU-z03A3avzQzIn66y3k,273
|
|
15
15
|
simo/__pycache__/settings.cpython-312.pyc,sha256=PE2CUT2j6Uj3xB5LpEEyw8q9MQLsoZPRgcOsUDh9y8o,6688
|
|
16
16
|
simo/__pycache__/settings.cpython-38.pyc,sha256=4w3ds3D9S78zbsovXsXC05PYBAafDrtsOhX14FT0YyE,6149
|
|
17
|
-
simo/__pycache__/urls.cpython-312.pyc,sha256=
|
|
17
|
+
simo/__pycache__/urls.cpython-312.pyc,sha256=mIg_YD7zgjmIzfWzpGpikMqanGKP2O-iuA1ixqQngnc,3689
|
|
18
18
|
simo/__pycache__/urls.cpython-38.pyc,sha256=u0x6EqT8S1YfDOSPgbI8Kf-RDlveY9OV-EDXMYKAQ7w,2125
|
|
19
19
|
simo/__pycache__/wsgi.cpython-38.pyc,sha256=TpRxO7VM_ql31hbKphVdanydC5RI1nHB4l0QA2pdWxo,322
|
|
20
20
|
simo/automation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
simo/automation/app_widgets.py,sha256=gaqImMZjuMHm7nIb9a4D-Y3qipz_WhSPAHXcwGx4Uzs,199
|
|
22
22
|
simo/automation/controllers.py,sha256=Ow8xG9hkdyMRZbrNPX5uZloYM9jZqa9mgCh4k6FeoJw,11492
|
|
23
23
|
simo/automation/forms.py,sha256=UWnkxw8pILPK0smRPTo4SLgsZl78zOySx7JIc30Bgtk,10228
|
|
24
|
-
simo/automation/gateways.py,sha256=
|
|
24
|
+
simo/automation/gateways.py,sha256=Hej6v2K6MM8ABh96nIvCvRy5PxggJuDhoJ5WtRBlClA,15672
|
|
25
25
|
simo/automation/helpers.py,sha256=iP-fxxB8HsFQy3k2CjFubu86aMqvWgmh-p24DiyOrek,4330
|
|
26
26
|
simo/automation/models.py,sha256=l45FHgeKGsfpLtd1X1PVFpIjB5JI4BlvKkodpcxm6aE,927
|
|
27
27
|
simo/automation/serializers.py,sha256=PjyFrjdPK1mBsgbNhyqMi9SWzcymqTa742ipy0LhAN4,1996
|
|
@@ -34,7 +34,7 @@ simo/automation/__pycache__/controllers.cpython-312.pyc,sha256=w2yAFvk-Fh1MZha7J
|
|
|
34
34
|
simo/automation/__pycache__/controllers.cpython-38.pyc,sha256=CL-0Tq9B4-E36fYfWT1XEBTq1dkq1W8003f6MrBnQU0,8391
|
|
35
35
|
simo/automation/__pycache__/forms.cpython-312.pyc,sha256=63rU0rWZk-Rz5qoMZiXl743WPc9NVm5d8bSd8w52T4E,12347
|
|
36
36
|
simo/automation/__pycache__/forms.cpython-38.pyc,sha256=cpA5hA2Iz3JsPC0Dq01ki1I7S9c5DKRcXveHApI1dJo,7772
|
|
37
|
-
simo/automation/__pycache__/gateways.cpython-312.pyc,sha256=
|
|
37
|
+
simo/automation/__pycache__/gateways.cpython-312.pyc,sha256=UMjaV_-JQRHC9I-tVnDxSZcRnvoOG59ZyJnkoLXBHfg,22129
|
|
38
38
|
simo/automation/__pycache__/gateways.cpython-38.pyc,sha256=nHujqChMCqqxHbZezP3MisavjKDhczqzFGurO10h-lc,11113
|
|
39
39
|
simo/automation/__pycache__/helpers.cpython-312.pyc,sha256=aDFtzBE72szi4gzVxK_NiAEC__wCmdztw0UKu2lVU58,5853
|
|
40
40
|
simo/automation/__pycache__/helpers.cpython-38.pyc,sha256=fNjSyn4Mfq7-JQx-bdsnj-rSxgu20dVJ9-5ZEMT6yiM,3627
|
|
@@ -312,6 +312,7 @@ simo/core/migrations/0045_alter_instance_device_report_history_days_and_more.py,
|
|
|
312
312
|
simo/core/migrations/0046_component_value_translation_alter_gateway_type.py,sha256=SUybDSLRCGevVS9mCQGvozO8LA43tKze3R5rCf1TQ4E,1282
|
|
313
313
|
simo/core/migrations/0047_alter_component_value_translation.py,sha256=3GAgUBkZKUwWJMbDJxJJLBicC8eKkQ2ZJA__-xYpBCo,733
|
|
314
314
|
simo/core/migrations/0048_publicfile_privatefile.py,sha256=3NAP6f1ep66-CHJ7olSYOnXXeN7fTAg76lEjTJE1rL8,1601
|
|
315
|
+
simo/core/migrations/0049_alter_gateway_type.py,sha256=Hs6-idTvebddqrFOs-HQY3m-HAq8e2ko2gMuf7TZBUo,797
|
|
315
316
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
316
317
|
simo/core/migrations/__pycache__/0001_initial.cpython-312.pyc,sha256=2qtefpMLlqb1zcvIAQcW1XHwAqa0777LybQncwIoTwM,10893
|
|
317
318
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=w6GiBXVxWj30Bg4Sn_pFVeA041d-pCrkaq8mR3KuF70,5381
|
|
@@ -409,6 +410,7 @@ simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-
|
|
|
409
410
|
simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-38.pyc,sha256=ucmaVOjI3q78vBTiEC7Aq76CklWq3fsC24EiH-mIzGc,961
|
|
410
411
|
simo/core/migrations/__pycache__/0048_publicfile_privatefile.cpython-312.pyc,sha256=R-e0LlBMXd48iYwYPx1FWBXMgkojbVTen0yzWAZ0qto,2331
|
|
411
412
|
simo/core/migrations/__pycache__/0048_publicfile_privatefile.cpython-38.pyc,sha256=Xtycj-4jvkB8UjVdgZZRzTgYl68Cr-Jj9WqCAho1Ggk,1346
|
|
413
|
+
simo/core/migrations/__pycache__/0049_alter_gateway_type.cpython-312.pyc,sha256=yRCnPOqiDfsxwhpsZpFetdRU-wwPmlcsko0naC9vs7w,1172
|
|
412
414
|
simo/core/migrations/__pycache__/__init__.cpython-312.pyc,sha256=BhHR8x2b6O7PeccXle2QiefejTa-RussOoAENjeUKnE,175
|
|
413
415
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=VZmDQ57BTcebuM0KMhjiTOabgWZCBxQmSJzWZos9SO8,169
|
|
414
416
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
@@ -10589,9 +10591,9 @@ simo/fleet/templates/fleet/controllers_info/ENS160AirQualitySensor.md,sha256=3LS
|
|
|
10589
10591
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10590
10592
|
simo/generic/app_widgets.py,sha256=y8W3jR76Hh26O9pPQyg2SophMbYIOtAWD33MPKbB8Mg,856
|
|
10591
10593
|
simo/generic/base_types.py,sha256=u3SlfpNYaCwkVBwomWgso4ODzL71ay9MhiAW-bxgnDU,341
|
|
10592
|
-
simo/generic/controllers.py,sha256=
|
|
10593
|
-
simo/generic/forms.py,sha256=
|
|
10594
|
-
simo/generic/gateways.py,sha256=
|
|
10594
|
+
simo/generic/controllers.py,sha256=HDhf-bC6WATWzHFFEndap4z213n0LgtBhVG1lfMxzMU,46597
|
|
10595
|
+
simo/generic/forms.py,sha256=N9Jv4-e2IroSAeXXrpdpThQnH2sw5ADh08nFtdOK9Ds,26035
|
|
10596
|
+
simo/generic/gateways.py,sha256=bq01qX2Q62B47yHmTKdCfQE8tcwmI70jvJko-pIyQag,17534
|
|
10595
10597
|
simo/generic/models.py,sha256=Adq7ipWK-renxJlNW-SZnAq2oGEOwKx8EdUWaKnfcVQ,7597
|
|
10596
10598
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10597
10599
|
simo/generic/socket_consumers.py,sha256=pyiqzfGxSKBNqfrfEJ_kCU0UbSC28XnvDn6QjKkbqyY,1767
|
|
@@ -10601,11 +10603,11 @@ simo/generic/__pycache__/app_widgets.cpython-312.pyc,sha256=ywoKk91YSEZxpyt9haG5
|
|
|
10601
10603
|
simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=D9b13pbMlirgHmjDnQhfLIDGSVINoSouHb4SWOeCRrs,1642
|
|
10602
10604
|
simo/generic/__pycache__/base_types.cpython-312.pyc,sha256=h8Mwu49i-zmwTbL33JaLJfRDGOgkQh2_VqrfzEc4UQ4,616
|
|
10603
10605
|
simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=aV5NdIuvXR-ItKpI__MwcyPZHD6Z882TFdgYkPCkr1I,493
|
|
10604
|
-
simo/generic/__pycache__/controllers.cpython-312.pyc,sha256=
|
|
10606
|
+
simo/generic/__pycache__/controllers.cpython-312.pyc,sha256=g5fjTUYYNFGR7Sv-hoES7Vfofc7bxMk0Ef6nGNhvgNM,53145
|
|
10605
10607
|
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=jJjwKVaDYyazrRGNjUFoY74nr_jX_DEnsC9KjyxZCgc,30427
|
|
10606
|
-
simo/generic/__pycache__/forms.cpython-312.pyc,sha256=
|
|
10608
|
+
simo/generic/__pycache__/forms.cpython-312.pyc,sha256=NtOAjTxXh0vaYNdUY9PVJy1Q9Bm_HiFX6oXxW5yQ62Y,34676
|
|
10607
10609
|
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=k8lz3taXdWAg5P9jcnw66mWH51pCc4SOsg32kVEtBCg,19416
|
|
10608
|
-
simo/generic/__pycache__/gateways.cpython-312.pyc,sha256=
|
|
10610
|
+
simo/generic/__pycache__/gateways.cpython-312.pyc,sha256=bq-k85HBSfg_EHtDFQmo1BMBDjgPqP0lfw5BEnP1vB4,21672
|
|
10609
10611
|
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=GIeMT51oZU2OCFD4eUDFdSRRYE0Qf14AcOr_gdUqG94,12705
|
|
10610
10612
|
simo/generic/__pycache__/models.cpython-312.pyc,sha256=xriUzjkaM2Y4mT3jo2OPK-XGBroBBSFJfLqK0jMA4MA,10200
|
|
10611
10613
|
simo/generic/__pycache__/models.cpython-38.pyc,sha256=MZpum7syAFxuulf47K7gtUlJJ7xRD-IBUBAwUM1ZRnw,5825
|
|
@@ -10648,43 +10650,44 @@ simo/generic/templates/admin/controller_widgets/weather.html,sha256=84SESQBhhzNU
|
|
|
10648
10650
|
simo/generic/templates/generic/controllers_info/dummy.md,sha256=DcdkpYXpK7sroINukZZPUQs9uekN9kkE7p5hfnArgFo,147
|
|
10649
10651
|
simo/generic/templates/generic/controllers_info/stateselect.md,sha256=T0w3vJg02W3RMSsljN1EPRnkVaeRW5acSZaSq9FYvZw,135
|
|
10650
10652
|
simo/multimedia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10651
|
-
simo/multimedia/admin.py,sha256=
|
|
10653
|
+
simo/multimedia/admin.py,sha256=gK6YuWVao52srVPVpR8R0muJcEvM7aMKd8F9AayNO2I,1047
|
|
10652
10654
|
simo/multimedia/api.py,sha256=mZ5BTggWdc_kL8P70JGC3rTCiZKPnxWYoyNcAQkFnX4,285
|
|
10653
10655
|
simo/multimedia/app_widgets.py,sha256=_M-HsUzlW1V2LxVw5SUH8Og9b4u0e179gCp-sFhfoPM,331
|
|
10654
|
-
simo/multimedia/auto_urls.py,sha256=
|
|
10656
|
+
simo/multimedia/auto_urls.py,sha256=dF9B1OZX_xpYbWgd3uR4IVeMIMMUS-zXqVjozaEfrUQ,310
|
|
10655
10657
|
simo/multimedia/base_types.py,sha256=dAP7_uh_b3A03yXBJZyQdRFucKIro4_RkIZ5yOaWXVE,151
|
|
10656
|
-
simo/multimedia/controllers.py,sha256=
|
|
10658
|
+
simo/multimedia/controllers.py,sha256=i9Q9j8WHuLwJBXZ2E0gQOLNu47QuH34MVEDW9mpGl5Q,3650
|
|
10657
10659
|
simo/multimedia/forms.py,sha256=oMCVUXRNiESrY3w_uBLRRgjMjx8BrmNeVglzorA9QtY,239
|
|
10658
|
-
simo/multimedia/models.py,sha256=
|
|
10660
|
+
simo/multimedia/models.py,sha256=Q5Fi8YARkimQ3uyKAAlv50XuqXzzOGCOaXha4G4IQ3g,1305
|
|
10659
10661
|
simo/multimedia/serializers.py,sha256=9DRGsJVJLKdqmOLiVHMY06bTTYxpABhDy1JB_klzsBw,383
|
|
10660
|
-
simo/multimedia/views.py,sha256=
|
|
10662
|
+
simo/multimedia/views.py,sha256=HWj4FYPRqCUc8l40lqdQAecHkNe0VhbO7kN9Bu7kNpc,2505
|
|
10661
10663
|
simo/multimedia/__pycache__/__init__.cpython-312.pyc,sha256=NGPM-a2cNEN2nd_L7dW3cRwes3B6ZnsH7vx3mSD3OUg,170
|
|
10662
10664
|
simo/multimedia/__pycache__/__init__.cpython-38.pyc,sha256=BOLHOifu6r_MuWjddGcQVsYkqYlkmHvPQIcx3selLIk,164
|
|
10663
|
-
simo/multimedia/__pycache__/admin.cpython-312.pyc,sha256=
|
|
10665
|
+
simo/multimedia/__pycache__/admin.cpython-312.pyc,sha256=emz0M7DQAsBzRHIzz9RjwEVn3EEA_lRTNPBYCELFbdU,1820
|
|
10664
10666
|
simo/multimedia/__pycache__/admin.cpython-38.pyc,sha256=xIax_AtzQlJiQmEBG5xuhJz2-Ztf40e26AQs5oBISfw,1309
|
|
10665
10667
|
simo/multimedia/__pycache__/api.cpython-312.pyc,sha256=H4g5L2s2btP8AJOe9s95X3AnElEj6GOM1IYEHh1_lTI,727
|
|
10666
10668
|
simo/multimedia/__pycache__/api.cpython-38.pyc,sha256=lFGEB74vgyEM98B42wwcN9WvH8FAupIiSY0SwEBd5Dw,605
|
|
10667
10669
|
simo/multimedia/__pycache__/app_widgets.cpython-312.pyc,sha256=mkhOltpNGI8pnKkr3G06yjPwhtpQNbxF-7DzckP39_Y,809
|
|
10668
10670
|
simo/multimedia/__pycache__/app_widgets.cpython-38.pyc,sha256=ZkTAF-us5U5mjc8fsT0z8lKA-6eRL4isl3tpqUqjlus,735
|
|
10669
|
-
simo/multimedia/__pycache__/auto_urls.cpython-312.pyc,sha256=
|
|
10671
|
+
simo/multimedia/__pycache__/auto_urls.cpython-312.pyc,sha256=dOonI_zazvAP6tVJboqrq-f8Z6YevELNhAVQWzy7PaI,552
|
|
10670
10672
|
simo/multimedia/__pycache__/auto_urls.cpython-38.pyc,sha256=JNI3pZNFC3NoJV4cxsy-Oe6Vc6TA9fpPU63hjlXWINE,357
|
|
10671
10673
|
simo/multimedia/__pycache__/base_types.cpython-312.pyc,sha256=jxgtUvy_XYES0ZaUnHylyDcG2dS1LlFqdJyenhUQ8k4,368
|
|
10672
10674
|
simo/multimedia/__pycache__/base_types.cpython-38.pyc,sha256=c4nmNziLs4RB3MAnxltn3W5XNW6PM5_vK_mm3Yvy42Y,324
|
|
10673
|
-
simo/multimedia/__pycache__/controllers.cpython-312.pyc,sha256=
|
|
10675
|
+
simo/multimedia/__pycache__/controllers.cpython-312.pyc,sha256=hEaVHg_wfOasxK5rgvZdIRnajmb2idwmea9h9t8FtfU,5943
|
|
10674
10676
|
simo/multimedia/__pycache__/controllers.cpython-38.pyc,sha256=sbWvA-ro93qWxV6Qk8Pv_WPsq91tqlnFPIvCeQ0tvLA,4997
|
|
10675
10677
|
simo/multimedia/__pycache__/forms.cpython-312.pyc,sha256=lMdfAkCN2zOgLfPAOBQzOIlcReFpL1BdsjwQ_XXaOfk,774
|
|
10676
10678
|
simo/multimedia/__pycache__/forms.cpython-38.pyc,sha256=99h7Yj2jim3QOrqej00wiPufrCF3F--RoYvwa6lzhPI,697
|
|
10677
|
-
simo/multimedia/__pycache__/models.cpython-312.pyc,sha256=
|
|
10679
|
+
simo/multimedia/__pycache__/models.cpython-312.pyc,sha256=FhSOj_gUPJhLBYuIu1u7hDV0cNScRBO2xoMOYj4ehjA,2630
|
|
10678
10680
|
simo/multimedia/__pycache__/models.cpython-38.pyc,sha256=LmQ_XMA--wvLq11xYp24nU-y-kbx17iEZ10y9twCMJ0,1662
|
|
10679
10681
|
simo/multimedia/__pycache__/serializers.cpython-312.pyc,sha256=XaavYbkW-tNPEkZyjWLW8gaqRwimECPTcuON213QBVw,1118
|
|
10680
10682
|
simo/multimedia/__pycache__/serializers.cpython-38.pyc,sha256=n86txYSrkmN0Xlrr8dMwKSY7rEzMc1iovepCZi_Fcw8,886
|
|
10681
|
-
simo/multimedia/__pycache__/views.cpython-312.pyc,sha256=
|
|
10683
|
+
simo/multimedia/__pycache__/views.cpython-312.pyc,sha256=OKgt7c7kbhjCqZ97cZTir1g8drp2c6v69KxF6ywi9t4,3870
|
|
10682
10684
|
simo/multimedia/__pycache__/views.cpython-38.pyc,sha256=yq5Hi2HrbSNr8MP4uUZO7_GMeVgqg21R6yFe85zNNhM,899
|
|
10683
10685
|
simo/multimedia/migrations/0001_initial.py,sha256=YxTbmI-aF9OZUkFPnCNqV3t3r5nSJg59pKcTvm-ZYbU,610
|
|
10684
10686
|
simo/multimedia/migrations/0002_sound_length.py,sha256=XpPemInQwL1QsiqhUPkdBPBYI2E5gDPyC_1vhyImq5M,471
|
|
10685
10687
|
simo/multimedia/migrations/0003_alter_sound_length.py,sha256=tt1OJVkrCo6Ybws1mGobdvTP5o68P3-cHZdGG_PeZwU,442
|
|
10686
10688
|
simo/multimedia/migrations/0004_auto_20231023_1055.py,sha256=ilH1o_wxkK5QDjcPEEDhoHWx2GcjZWLG6XjlUfQRmhI,718
|
|
10687
10689
|
simo/multimedia/migrations/0005_remove_sound_slug_sound_date_uploaded.py,sha256=SzkgIhCIEVMSmxVwGHQfggdsX4wWybvskqVx-vVp2Qs,602
|
|
10690
|
+
simo/multimedia/migrations/0006_remove_sound_length_sound_duration.py,sha256=aVw9gi5FfVuH_U0acnPEsl48DEPSiO5r8EK0UI1b4-M,572
|
|
10688
10691
|
simo/multimedia/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10689
10692
|
simo/multimedia/migrations/__pycache__/0001_initial.cpython-312.pyc,sha256=2glBfOpmU6Sp3RExZ41jiwzGPWl8JvaUtPBWYUF7gWg,1063
|
|
10690
10693
|
simo/multimedia/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=slsqUkj8A11Oj5bYJ1s5dS60Qx4H9k_oRZ3HaAhuho4,760
|
|
@@ -10696,6 +10699,7 @@ simo/multimedia/migrations/__pycache__/0004_auto_20231023_1055.cpython-312.pyc,s
|
|
|
10696
10699
|
simo/multimedia/migrations/__pycache__/0004_auto_20231023_1055.cpython-38.pyc,sha256=tX6x1gNeVcUHcCFvisP9Z2jPBE029TJG632fvtvUjV8,892
|
|
10697
10700
|
simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-312.pyc,sha256=gGYLNmOVIrh2TjsxjVRbcLXQI46mwV_0e14mEVHWITo,1066
|
|
10698
10701
|
simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-38.pyc,sha256=vpu4EfpVp5rYRKYEVn4vDylgpeasD31ZV62sNR_HXhY,801
|
|
10702
|
+
simo/multimedia/migrations/__pycache__/0006_remove_sound_length_sound_duration.cpython-312.pyc,sha256=kn0T_kxdq5dFspvXcDnp_i0ilnF7ssZYUZZLh5E9DqA,962
|
|
10699
10703
|
simo/multimedia/migrations/__pycache__/__init__.cpython-312.pyc,sha256=63PjzEbaT7KQ3tQSmpMvM3ry31Eu40r7Zq8C4y2z6FY,181
|
|
10700
10704
|
simo/multimedia/migrations/__pycache__/__init__.cpython-38.pyc,sha256=mCgSiQBphL85imdWyTi9-4zBDYF6HfXbhB0ycSPVVuA,175
|
|
10701
10705
|
simo/multimedia/templates/admin/controller_widgets/player.html,sha256=v4PFoL37-C7L6ILZI6yF5ff9iO3EnEs5kXbRayaHy0s,358
|
|
@@ -10920,9 +10924,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10920
10924
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10921
10925
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10922
10926
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10923
|
-
simo-2.7.
|
|
10924
|
-
simo-2.7.
|
|
10925
|
-
simo-2.7.
|
|
10926
|
-
simo-2.7.
|
|
10927
|
-
simo-2.7.
|
|
10928
|
-
simo-2.7.
|
|
10927
|
+
simo-2.7.16.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10928
|
+
simo-2.7.16.dist-info/METADATA,sha256=uuLTNmwN-BR8ZrQ9eBFoXWOf1Roj8fqHPUdwJNlA-5k,2009
|
|
10929
|
+
simo-2.7.16.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
10930
|
+
simo-2.7.16.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
|
|
10931
|
+
simo-2.7.16.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10932
|
+
simo-2.7.16.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|