diff --git a/django_code/apps/betaserie/utils.py b/django_code/apps/betaserie/utils.py
index 10e0be6..e4a6ad7 100644
--- a/django_code/apps/betaserie/utils.py
+++ b/django_code/apps/betaserie/utils.py
@@ -63,18 +63,19 @@ class betaserieUtils():
def identify_episode(self,show_id,episode_number,verbose=False):
#
# Usage
- # episode_id = beta.identify_episode(show_id,"S01E01",True)
+ # episode_id,episode_seen = beta.identify_episode(show_id,"S01E01",True)
#
url = "https://api.betaseries.com/episodes/search?show_id="+str(show_id)+"&number="+str(episode_number)
response = requests.request("GET", url, headers=self.headers, data=self.payload)
episode_id = response.json()['episode']['id']
+ episode_seen = response.json()['episode']['user']['seen']
if verbose:
print("Url request: "+str(url))
print(response.text)
- return episode_id
+ return episode_id,episode_seen
def mark_episodes_watched(self,episode_id,verbose=False):
#
@@ -112,11 +113,21 @@ class betaserieUtils():
url = "https://api.betaseries.com/shows/display?id="+str(show_id)
response = requests.request("GET", url, headers=self.headers, data=self.payload)
- maximum_number_seasons = response.json()['show']['seasons']
- if verbose : print("maximum_number_seasons: "+str(maximum_number_seasons))
-
seasons_details = response.json()['show']['seasons_details']
+
+ #checking if the first season is season 0, and if so remove this season
+ if (seasons_details[0]['number']==0):
+ season_0_to_remove = seasons_details[0]
+
+ if verbose : print(season_0_to_remove)
+
+ seasons_details.remove(season_0_to_remove)
+ maximum_number_seasons = len(seasons_details)
+
+ if verbose : print("maximum_number_seasons: "+str(maximum_number_seasons))
+
+
if verbose:
print("Url request: "+str(url))
print(response.text)
diff --git a/django_code/apps/cloudmanager/apps.py b/django_code/apps/cloudmanager/apps.py
index 1010f1c..3256025 100644
--- a/django_code/apps/cloudmanager/apps.py
+++ b/django_code/apps/cloudmanager/apps.py
@@ -3,7 +3,7 @@ from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import render
import os
-import psycopg2
+#import psycopg2
from apps.cloudmanager.db_interaction import DB_generation,Check_server_supposed_XXX,Give_current_weekday,Give_current_hour
diff --git a/django_code/apps/cloudmanager/db_interaction.py b/django_code/apps/cloudmanager/db_interaction.py
index 2d018e7..309f9b8 100644
--- a/django_code/apps/cloudmanager/db_interaction.py
+++ b/django_code/apps/cloudmanager/db_interaction.py
@@ -1,4 +1,4 @@
-import psycopg2
+#import psycopg2
from django.http import HttpResponse
from django.views.decorators.http import require_POST
from apps.kubernetes_connection import apps as kubernetes_connection
diff --git a/django_code/apps/random_simpsons/utils.py b/django_code/apps/random_simpsons/utils.py
index 51f0f77..c1788ad 100644
--- a/django_code/apps/random_simpsons/utils.py
+++ b/django_code/apps/random_simpsons/utils.py
@@ -22,7 +22,7 @@ def mark_episode_watched(season,episode,action,verbose=False):
#mark episode as seen in betaserie
episode_number = "S"+str(season)+"E"+str(episode)
- episode_id = betaserie.identify_episode(simpsons_id,episode_number)
+ episode_id,episode_seen = betaserie.identify_episode(simpsons_id,episode_number)
if action == "watched":
betaserie.mark_episodes_watched(episode_id)
@@ -49,20 +49,16 @@ def generate_new_urls_for_episode(verbose=False):
# URL.com/simpsons/season=XX&episode=XX
# example
# https://www.1shows.org/tv/456-the-simpsons?streaming=true&season=33&episode=18
+
+ seasons_information,maximum_number_season = betaserie.series_information(simpsons_id)
- simpsons_series_information = betaserie.series_information(simpsons_id)
- seasons_information = simpsons_series_information[0]
#for the simpsons, there is a season 0 which increase the count of seasons by 1
# we need to remove this entry ,
# so we cannot trust the maximum_number_season coming from simpsons_series_information
- season_0_to_remove = seasons_information[0]
-
- if verbose : print(season_0_to_remove)
-
- seasons_information.remove(season_0_to_remove)
- maximum_number_season = len(seasons_information)
+ # edit 26/08/2026
+ # I updated the function betaserie.series_information to remove this season 0
for season in range(1,maximum_number_season+1):
# the list doesn't start with season 0 anymore so we cannot use the season number as index
diff --git a/django_code/apps/streaming/admin.py b/django_code/apps/streaming/admin.py
index bb77350..1b3bd20 100644
--- a/django_code/apps/streaming/admin.py
+++ b/django_code/apps/streaming/admin.py
@@ -87,6 +87,6 @@ class StreamingRedirectAdmin(ImportExportModelAdmin):
(
'Information', {
"classes": ["collapse"],
- 'fields': ('seasonInformation','alias','betaserieShowId')
+ 'fields': ('seasonInformation','alias','betaserieShowId','maximumNumberSeason')
}),
)
\ No newline at end of file
diff --git a/django_code/apps/streaming/migrations/0013_streamingredirectdata_maximumnumberseason.py b/django_code/apps/streaming/migrations/0013_streamingredirectdata_maximumnumberseason.py
new file mode 100644
index 0000000..5cd407b
--- /dev/null
+++ b/django_code/apps/streaming/migrations/0013_streamingredirectdata_maximumnumberseason.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.30 on 2026-08-26 11:26
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('streaming', '0012_alter_streamingredirectdata_betaserieshowid'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='streamingredirectdata',
+ name='maximumNumberSeason',
+ field=models.IntegerField(blank=True, null=True),
+ ),
+ ]
diff --git a/django_code/apps/streaming/models.py b/django_code/apps/streaming/models.py
index 3256e10..6bef159 100644
--- a/django_code/apps/streaming/models.py
+++ b/django_code/apps/streaming/models.py
@@ -28,6 +28,7 @@ class StreamingRedirectData(models.Model):
alias = models.CharField(max_length=1000, null=True,blank=True)
seasonInformation = models.JSONField(default=dict, blank=True)
betaserieShowId = models.IntegerField(null=True,blank=True)
+ maximumNumberSeason = models.IntegerField(null=True,blank=True)
randomViewing = models.BooleanField(default=False)
def sanitize(self, name):
@@ -38,7 +39,13 @@ class StreamingRedirectData(models.Model):
print(serie_name)
print(betaserie.identify_serie(serie_name))
return betaserie.series_information(betaserie.identify_serie(serie_name))[0]
-
+
+ def maximum_Number_Season(self, serie_name):
+ betaserie = betaserieUtils()
+ print(serie_name)
+ print(betaserie.identify_serie(serie_name))
+ return betaserie.series_information(betaserie.identify_serie(serie_name))[1]
+
def betaserie_show_id(self,serie_name):
betaserie = betaserieUtils()
print(serie_name)
@@ -46,6 +53,7 @@ class StreamingRedirectData(models.Model):
return betaserie.identify_serie(serie_name)
+
def save(self, *args, **kwargs):
if not self.seasonInformation :
self.seasonInformation = self.season_information(self.name)
@@ -53,6 +61,8 @@ class StreamingRedirectData(models.Model):
self.alias = self.sanitize(self.name)
if not self.betaserieShowId:
self.betaserieShowId = self.betaserie_show_id(self.name)
+ if not self.maximumNumberSeason:
+ self.maximumNumberSeason = self.maximum_Number_Season(self.name)
super().save(*args, **kwargs)
class Meta:
diff --git a/django_code/apps/streaming/utils.py b/django_code/apps/streaming/utils.py
index 40f31c4..065284b 100644
--- a/django_code/apps/streaming/utils.py
+++ b/django_code/apps/streaming/utils.py
@@ -1,6 +1,7 @@
import requests
from django.conf import settings
-
+from apps.betaserie.utils import betaserieUtils
+import random
def full_testing(url_website):
status = "unknown"
@@ -38,18 +39,26 @@ def test_website(url_website,bool_proxy=False):
return status
-def randomEpisode():
- return 0,0
+def randomEpisode(seasonInformation,maximum_number_of_seasons):
+ random_season = random.randint(1, maximum_number_of_seasons)
+ print("random season: " + str(random_season))
-def followingEpisode(season,episode,seasonInformation):
+ maximum_number_of_episodes = seasonInformation[random_season-1]['episodes']
+
+ random_episode = random.randint(1, maximum_number_of_episodes)
+ print("random episode: " + str(random_episode))
+
+ return random_season,random_episode
+
+def followingEpisode(season,episode,seasonInformation,maximum_number_seasons):
lastEpisode = False
#check if the episode is the last one of the season
- if (episode < seasonInformation[season]['episodes']):
- #the current episode is not the
+ if (episode < seasonInformation[season-1]['episodes']):
+ #the current episode is not the last one of the season
episode += 1
#check if the season is the last one
- elif((season+1) < (len(seasonInformation)-1)):
+ elif((season+1) < maximum_number_seasons):
season += 1
episode = 1
else:
diff --git a/django_code/apps/streaming/views.py b/django_code/apps/streaming/views.py
index 1c56fdc..d5a0507 100644
--- a/django_code/apps/streaming/views.py
+++ b/django_code/apps/streaming/views.py
@@ -5,6 +5,7 @@ from .models import StreamingRedirectData
from .utils import randomEpisode,followingEpisode
from apps.betaserie.utils import betaserieUtils
+
betaserie = betaserieUtils()
@@ -19,6 +20,8 @@ def streamingRedirect(request,alias):
episode = streaming_object.values('episode')[0]['episode']
season = streaming_object.values('season')[0]['season']
seasonInformation = streaming_object.values('seasonInformation')[0]['seasonInformation']
+ maximumNumberSeason = streaming_object.values('maximumNumberSeason')[0]['maximumNumberSeason']
+
url_prefix = streaming_object.values('prefix')[0]['prefix']
url_infix = streaming_object.values('infix')[0]['infix']
@@ -26,29 +29,35 @@ def streamingRedirect(request,alias):
betaserieShowId = streaming_object.values('betaserieShowId')[0]['betaserieShowId']
- print(url_prefix)
-
- print(season)
- print(episode)
+ print("Last episode seen:")
+ print("Season: "+str(season))
+ print("Episode: "+str(episode))
print(seasonInformation)
+
- value = str(streaming_object.values('url_example'))
- print(value)
+ randomViewing = streaming_object.values('randomViewing')[0]['randomViewing']
+ print("randomViewing: "+str(randomViewing))
- url_example = str(streaming_object.values('url_example')[0]['url_example'])
- print(url_example)
-
- randomViewing =str(streaming_object.values('randomViewing')[0]['randomViewing'])
- print(randomViewing)
-
- if (randomViewing == False):
+ if (randomViewing == True):
print('show set to random')
- season,episode = randomEpisode()
+ boolean_restart = True;
+ while (boolean_restart):
+ season,episode = randomEpisode(seasonInformation,maximumNumberSeason)
+ episode_number = "S"+str(season)+"E"+str(episode)
+
+ episode_id,episode_seen = betaserie.identify_episode(betaserieShowId,episode_number)
+ print("episode_seen: "+str(episode_seen))
+
+ if not(episode_seen):
+ boolean_restart = False
+ else:
+ print("episode "+str(episode)+" from season "+str(season)+" already seen")
+
else:
print('show set to following episode')
- season,episode,lastEpisode = followingEpisode(season,episode,seasonInformation)
+ season,episode,lastEpisode = followingEpisode(season,episode,seasonInformation,maximumNumberSeason)
if (lastEpisode):
return HttpResponse('
You already watched the last episode of the serie!
')
@@ -68,9 +77,8 @@ def streamingRedirect(request,alias):
#mark episode as seen in betaserie
episode_number = "S"+str(season)+"E"+str(episode)
- episode_id = betaserie.identify_episode(betaserieShowId,episode_number)
+ episode_id,episode_seen = betaserie.identify_episode(betaserieShowId,episode_number)
betaserie.mark_episodes_watched(episode_id)
-
return redirect(str(url_generated))
\ No newline at end of file
diff --git a/django_code/templates/static/djangoql/css/completion.css b/django_code/templates/static/djangoql/css/completion.css
new file mode 100644
index 0000000..58fc1c7
--- /dev/null
+++ b/django_code/templates/static/djangoql/css/completion.css
@@ -0,0 +1,85 @@
+.djangoql-completion {
+ position: absolute;
+ display: none;
+ border: solid 1px #ccc;
+ border-radius: 4px;
+ background: white;
+ background: var(--body-bg, white);
+ min-width: 183px;
+ font-size: 13px;
+}
+
+.djangoql-completion .active {
+ background-color: #79aec8;
+ color: white;
+}
+
+.djangoql-completion ul {
+ padding: 2px 0;
+ margin: 0;
+ max-height: 295px;
+ overflow: auto;
+}
+
+.djangoql-completion li {
+ list-style: none;
+ padding: 4px 10px;
+ cursor: pointer;
+}
+
+.djangoql-completion li:hover {
+ background-color: #c4e9fa;
+ color: black;
+}
+
+.djangoql-completion li i {
+ font-size: 0.9em;
+ color: #ccc;
+ float: right;
+ font-style: normal;
+}
+
+.djangoql-completion .syntax-help {
+ padding: 4px 10px 6px 10px;
+ margin: 0;
+ border-top: solid 1px #ccc;
+ font-size: inherit;
+}
+
+/*
+Pure CSS loading icon. Credit: https://loading.io/css/
+*/
+.djangoql-loading {
+ display: block;
+ position: relative;
+}
+
+.djangoql-loading:after {
+ -moz-animation: djangoql-loading 1.2s linear infinite;
+ -ms-animation: djangoql-loading 1.2s linear infinite;
+ -webkit-animation: djangoql-loading 1.2s linear infinite;
+ animation: djangoql-loading 1.2s linear infinite;
+ border: 2px solid #aaa;
+ border-color: #aaa transparent #aaa transparent;
+ border-radius: 50%;
+ content: " ";
+ display: block;
+ height: 12px;
+ left: 50%;
+ margin: -8px;
+ position: absolute;
+ top: 50%;
+ width: 12px;
+}
+
+@keyframes djangoql-loading {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+
+/*# sourceMappingURL=completion.css.map*/
\ No newline at end of file
diff --git a/django_code/templates/static/djangoql/css/completion.css.map b/django_code/templates/static/djangoql/css/completion.css.map
new file mode 100644
index 0000000..194c015
--- /dev/null
+++ b/django_code/templates/static/djangoql/css/completion.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///./node_modules/djangoql-completion/dist/completion.css"],"names":[],"mappings":"AAAA;EACE,kBAAkB;EAClB,aAAa;EACb,sBAAsB;EACtB,kBAAkB;EAClB,iBAAiB;EACjB,iCAAiC;EACjC,gBAAgB;EAChB,eAAe;AACjB;;AAEA;EACE,yBAAyB;EACzB,YAAY;AACd;;AAEA;EACE,cAAc;EACd,SAAS;EACT,iBAAiB;EACjB,cAAc;AAChB;;AAEA;EACE,gBAAgB;EAChB,iBAAiB;EACjB,eAAe;AACjB;;AAEA;EACE,yBAAyB;EACzB,YAAY;AACd;;AAEA;EACE,gBAAgB;EAChB,WAAW;EACX,YAAY;EACZ,kBAAkB;AACpB;;AAEA;EACE,0BAA0B;EAC1B,SAAS;EACT,0BAA0B;EAC1B,kBAAkB;AACpB;;AAEA;;CAEC;AACD;EACE,cAAc;EACd,kBAAkB;AACpB;;AAEA;EACE,qDAAqD;EACrD,oDAAoD;EACpD,wDAAwD;EACxD,gDAAgD;EAChD,sBAAsB;EACtB,+CAA+C;EAC/C,kBAAkB;EAClB,YAAY;EACZ,cAAc;EACd,YAAY;EACZ,SAAS;EACT,YAAY;EACZ,kBAAkB;EAClB,QAAQ;EACR,WAAW;AACb;;AAEA;EACE;IACE,uBAAuB;EACzB;EACA;IACE,yBAAyB;EAC3B;AACF","file":"css/completion.css","sourcesContent":[".djangoql-completion {\n position: absolute;\n display: none;\n border: solid 1px #ccc;\n border-radius: 4px;\n background: white;\n background: var(--body-bg, white);\n min-width: 183px;\n font-size: 13px;\n}\n\n.djangoql-completion .active {\n background-color: #79aec8;\n color: white;\n}\n\n.djangoql-completion ul {\n padding: 2px 0;\n margin: 0;\n max-height: 295px;\n overflow: auto;\n}\n\n.djangoql-completion li {\n list-style: none;\n padding: 4px 10px;\n cursor: pointer;\n}\n\n.djangoql-completion li:hover {\n background-color: #c4e9fa;\n color: black;\n}\n\n.djangoql-completion li i {\n font-size: 0.9em;\n color: #ccc;\n float: right;\n font-style: normal;\n}\n\n.djangoql-completion .syntax-help {\n padding: 4px 10px 6px 10px;\n margin: 0;\n border-top: solid 1px #ccc;\n font-size: inherit;\n}\n\n/*\nPure CSS loading icon. Credit: https://loading.io/css/\n*/\n.djangoql-loading {\n display: block;\n position: relative;\n}\n\n.djangoql-loading:after {\n -moz-animation: djangoql-loading 1.2s linear infinite;\n -ms-animation: djangoql-loading 1.2s linear infinite;\n -webkit-animation: djangoql-loading 1.2s linear infinite;\n animation: djangoql-loading 1.2s linear infinite;\n border: 2px solid #aaa;\n border-color: #aaa transparent #aaa transparent;\n border-radius: 50%;\n content: \" \";\n display: block;\n height: 12px;\n left: 50%;\n margin: -8px;\n position: absolute;\n top: 50%;\n width: 12px;\n}\n\n@keyframes djangoql-loading {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n"],"sourceRoot":""}
\ No newline at end of file
diff --git a/django_code/templates/static/djangoql/css/completion_admin.css b/django_code/templates/static/djangoql/css/completion_admin.css
new file mode 100644
index 0000000..053349f
--- /dev/null
+++ b/django_code/templates/static/djangoql/css/completion_admin.css
@@ -0,0 +1,31 @@
+#changelist #toolbar form textarea#searchbar {
+ width: 80%;
+}
+
+.djangoql-toggle {
+ margin-right: 10px;
+}
+
+.djangoql-help {
+ display: inline-block;
+ float: right;
+ margin-right: 30px;
+}
+
+@media (max-width: 1024px) {
+ .djangoql-help {
+ margin-right: 20px;
+ }
+}
+
+@media (max-width: 767px) {
+ .djangoql-help {
+ margin-right: 5px;
+ }
+}
+
+.clearfix::after {
+ content: "";
+ clear: both;
+ display: table;
+}
diff --git a/django_code/templates/static/djangoql/css/syntax_help.css b/django_code/templates/static/djangoql/css/syntax_help.css
new file mode 100644
index 0000000..43ad5e7
--- /dev/null
+++ b/django_code/templates/static/djangoql/css/syntax_help.css
@@ -0,0 +1,14 @@
+code {
+ background-color: rgba(27, 31, 35, 0.05);
+ padding: 0.2em;
+}
+
+pre {
+ background-color: rgba(27, 31, 35, 0.05);
+ padding: 5px 40px;
+ margin: 0 0 10px 0;
+}
+
+table {
+ margin: 10px 0;
+}
diff --git a/django_code/templates/static/djangoql/img/completion_example.png b/django_code/templates/static/djangoql/img/completion_example.png
new file mode 100644
index 0000000..b364229
Binary files /dev/null and b/django_code/templates/static/djangoql/img/completion_example.png differ
diff --git a/django_code/templates/static/djangoql/img/completion_example_scaled.png b/django_code/templates/static/djangoql/img/completion_example_scaled.png
new file mode 100644
index 0000000..1c0dc8f
Binary files /dev/null and b/django_code/templates/static/djangoql/img/completion_example_scaled.png differ
diff --git a/django_code/templates/static/djangoql/js/completion.js b/django_code/templates/static/djangoql/js/completion.js
new file mode 100644
index 0000000..a3e2bba
--- /dev/null
+++ b/django_code/templates/static/djangoql/js/completion.js
@@ -0,0 +1,2 @@
+!function(){var t={57:function(t,e,n){function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t){"function"!=typeof t&&(t=o.defunct);var e=[],n=[],i=0;function s(){for(var t=[],e=0,i=this.state,o=this.index,s=this.input,r=0,l=n.length;r=0||i%2&&1===u&&!c[0]){var h=a.pattern;h.lastIndex=o;var p=h.exec(s);if(p&&p.index===o){var d=t.push({result:p,action:a.action,length:p[0].length});for(a.global&&(e=d);--d>e;){var f=d-1;if(t[d].length>t[f].length){var m=t[d];t[d]=t[f],t[f]=m}}}}}return t}this.state=0,this.index=0,this.input="",this.addRule=function(t,e,i){var o=t.global;if(!o){var s="g";t.multiline&&(s+="m"),t.ignoreCase&&(s+="i"),t=new RegExp(t.source,s)}return"[object Array]"!==Object.prototype.toString.call(i)&&(i=[0]),n.push({pattern:t,global:o,action:e,start:i}),this},this.setInput=function(t){return i=0,this.state=0,this.index=0,e.length=0,this.input=t,this},this.lex=function(){if(e.length)return e.shift();for(this.reject=!0;this.index<=this.input.length;){for(var n=s.call(this).splice(i),o=this.index;n.length&&this.reject;){var r=n.shift(),l=r.result,a=r.length;this.index+=a,this.reject=!1,i++;var c=r.action.apply(this,l);if(this.reject)this.index=l.index;else if(void 0!==c)switch(Object.prototype.toString.call(c)){case"[object Array]":e=c.slice(1),c=c[0];default:return a&&(i=0),c}}var u=this.input;if(o=e||n<0||g&&t-f>=u}function w(){var t=o();if(x(t))return S(t);p=setTimeout(w,function(t){var n=e-(t-d);return g?l(n,u-(t-f)):n}(t))}function S(t){return p=void 0,y&&a?v(t):(a=c=void 0,h)}function E(){var t=o(),n=x(t);if(a=arguments,c=this,d=t,n){if(void 0===p)return b(d);if(g)return clearTimeout(p),p=setTimeout(w,e),v(d)}return void 0===p&&(p=setTimeout(w,e)),h}return e=s(e)||0,i(n)&&(m=!!n.leading,u=(g="maxWait"in n)?r(s(n.maxWait)||0,e):u,y="trailing"in n?!!n.trailing:y),E.cancel=function(){void 0!==p&&clearTimeout(p),f=0,a=d=c=p=void 0},E.flush=function(){return void 0===p?h:S(o())},E}},716:function(t){function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports=function(t){var n=e(t);return null!=t&&("object"==n||"function"==n)}},667:function(t){function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports=function(t){return null!=t&&"object"==e(t)}},570:function(t,e,n){function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=n(807),s=n(667);t.exports=function(t){return"symbol"==i(t)||s(t)&&"[object Symbol]"==o(t)}},244:function(t,e,n){var i=n(366);t.exports=function(){return i.Date.now()}},167:function(t,e,n){var i=n(645),o=n(716);t.exports=function(t,e,n){var s=!0,r=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return o(n)&&(s="leading"in n?!!n.leading:s,r="trailing"in n?!!n.trailing:r),i(t,e,{leading:s,maxWait:e,trailing:r})}},666:function(t,e,n){var i=n(182),o=n(716),s=n(570),r=/^[-+]0x[0-9a-f]+$/i,l=/^0b[01]+$/i,a=/^0o[0-7]+$/i,c=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(s(t))return NaN;if(o(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=o(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=i(t);var n=l.test(t);return n||a.test(t)?c(t.slice(2),n?2:8):r.test(t)?NaN:+t}}},e={};function n(i){var o=e[i];if(void 0!==o)return o.exports;var s=e[i]={id:i,loaded:!1,exports:{}};return t[i](s,s.exports,n),s.loaded=!0,s.exports}n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,{a:e}),e},n.d=function(t,e){for(var i in e)n.o(e,i)&&!n.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t},function(){"use strict";var t=n(57),e=n.n(t),i=n(645),o=n.n(i),s=n(716),r=n.n(s),l=n(167),a=n.n(l);function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function u(t){this.size=0,this.limit=t,this.oldest=this.newest=void 0,this._keymap={}}u.prototype._markEntryAsUsed=function(t){t!==this.newest&&(t.newer&&(t===this.oldest&&(this.oldest=t.newer),t.newer.older=t.older),t.older&&(t.older.newer=t.newer),t.newer=void 0,t.older=this.newest,this.newest&&(this.newest.newer=t),this.newest=t)},u.prototype.put=function(t,e){var n=this._keymap[t];return n?(n.value=e,void this._markEntryAsUsed(n)):(this._keymap[t]=n={key:t,value:e,older:void 0,newer:void 0},this.newest?(this.newest.newer=n,n.older=this.newest):this.oldest=n,this.newest=n,this.size++,this.size>this.limit?this.shift():void 0)},u.prototype.shift=function(){var t=this.oldest;return t&&(this.oldest.newer?(this.oldest=this.oldest.newer,this.oldest.older=void 0):(this.oldest=void 0,this.newest=void 0),t.newer=t.older=void 0,delete this._keymap[t.key],this.size--),t},u.prototype.get=function(t,e){var n=this._keymap[t];if(void 0!==n)return this._markEntryAsUsed(n),e?n:n.value},u.prototype.find=function(t){return this._keymap[t]},u.prototype.set=function(t,e){var n,i=this.get(t,!0);return i?(n=i.value,i.value=e):(n=this.put(t,e))&&(n=n.value),n},u.prototype.remove=function(t){var e=this._keymap[t];if(e)return delete this._keymap[e.key],e.newer&&e.older?(e.older.newer=e.newer,e.newer.older=e.older):e.newer?(e.newer.older=void 0,this.oldest=e.newer):e.older?(e.older.newer=void 0,this.newest=e.older):this.oldest=this.newest=void 0,this.size--,e.value},u.prototype.removeAll=function(){this.oldest=this.newest=void 0,this.size=0,this._keymap={}},"function"==typeof Object.keys?u.prototype.keys=function(){return Object.keys(this._keymap)}:u.prototype.keys=function(){var t=[];for(var e in this._keymap)t.push(e);return t},u.prototype.forEach=function(t,e,n){var i;if(!0===e?(n=!0,e=void 0):"object"!==c(e)&&(e=this),n)for(i=this.newest;i;)t.call(e,i.key,i.value,this),i=i.older;else for(i=this.oldest;i;)t.call(e,i.key,i.value,this),i=i.newer},u.prototype.toJSON=function(){for(var t=new Array(this.size),e=0,n=this.oldest;n;)t[e++]={key:n.key,value:n.value},n=n.newer;return t},u.prototype.toString=function(){for(var t="",e=this.oldest;e;)t+=String(e.key)+":"+e.value,(e=e.newer)&&(t+=" < ");return t};var h=u;function p(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function d(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n".concat(i,"")),{text:t,snippetBefore:e||"",snippetAfter:n||"",suggestionText:o}}T.addRule(k,(function(){})),T.addRule(/\./,(function(t){return N("DOT",t)})),T.addRule(/,/,(function(t){return N("COMMA",t)})),T.addRule(new RegExp("or".concat(L)),(function(t){return N("OR",t)})),T.addRule(new RegExp("and".concat(L)),(function(t){return N("AND",t)})),T.addRule(new RegExp("not".concat(L)),(function(t){return N("NOT",t)})),T.addRule(new RegExp("in".concat(L)),(function(t){return N("IN",t)})),T.addRule(new RegExp("startswith".concat(L)),(function(t){return N("STARTSWITH",t)})),T.addRule(new RegExp("endswith".concat(L)),(function(t){return N("ENDSWITH",t)})),T.addRule(new RegExp("True".concat(L)),(function(t){return N("TRUE",t)})),T.addRule(new RegExp("False".concat(L)),(function(t){return N("FALSE",t)})),T.addRule(new RegExp("None".concat(L)),(function(t){return N("NONE",t)})),T.addRule(/[_A-Za-z][_0-9A-Za-z]*(\.[_A-Za-z][_0-9A-Za-z]*)*/,(function(t){return N("NAME",t)})),T.addRule(j,(function(t){return N("STRING_VALUE",t.slice(1,t.length-1))})),T.addRule(b,(function(t){return N("INT_VALUE",t)})),T.addRule(x,(function(t){return N("FLOAT_VALUE",t)})),T.addRule(/\(/,(function(t){return N("PAREN_L",t)})),T.addRule(/\)/,(function(t){return N("PAREN_R",t)})),T.addRule(/=/,(function(t){return N("EQUALS",t)})),T.addRule(/!=/,(function(t){return N("NOT_EQUALS",t)})),T.addRule(/>/,(function(t){return N("GREATER",t)})),T.addRule(/>=/,(function(t){return N("GREATER_EQUAL",t)})),T.addRule(/,(function(t){return N("LESS",t)})),T.addRule(/<=/,(function(t){return N("LESS_EQUAL",t)})),T.addRule(/~/,(function(t){return N("CONTAINS",t)})),T.addRule(/!~/,(function(t){return N("NOT_CONTAINS",t)})),T.lexAll=function(){for(var t,e=[];t=this.lex();)t.start=this.index-t.value.length,t.end=this.index,e.push(t);return e};var _=function(t){var e=100;this.options=t,this.currentModel=null,this.models={},this.suggestionsAPIUrl=null,this.token=N,this.lexer=T,this.prefix="",this.suggestions=[],this.selected=null,this.valuesCaseSensitive=!1,this.highlightCaseSensitive=!0,this.textarea=null,this.completion=null,this.completionUL=null,this.completionEnabled=!1,r()(t)?(this.loadIntrospections(t.introspections),"string"==typeof t.selector?this.textarea=document.querySelector(t.selector):this.textarea=t.selector,this.textarea?"TEXTAREA"===this.textarea.tagName?(t.valuesCaseSensitive&&(this.valuesCaseSensitive=!0),t.cacheSize&&(parseInt(t.cacheSize,10)!==t.cacheSize||t.cacheSize<1?this.logError("cacheSize must be a positive integer"):e=t.cacheSize),this.suggestionsCache=new h(e),this.debouncedLoadFieldOptions=o()(this.loadFieldOptions.bind(this),300),this.loading=!1,this.enableCompletion=this.enableCompletion.bind(this),this.disableCompletion=this.disableCompletion.bind(this),this.onCompletionMouseClick=this.onCompletionMouseClick.bind(this),this.onCompletionMouseDown=this.onCompletionMouseDown.bind(this),this.popupCompletion=this.popupCompletion.bind(this),this.debouncedRenderCompletion=o()(this.renderCompletion.bind(this),50),this.textarea.setAttribute("autocomplete","off"),this.textarea.addEventListener("keydown",this.onKeydown.bind(this)),this.textarea.addEventListener("blur",this.hideCompletion.bind(this)),this.textarea.addEventListener("click",this.popupCompletion),t.autoResize?(this.textareaResize=this.textareaResize.bind(this),this.textarea.style.resize="none",this.textarea.style.overflow="hidden",this.textarea.addEventListener("input",this.textareaResize),this.textareaResize(),window.addEventListener("load",this.textareaResize)):(this.textareaResize=null,this.textarea.addEventListener("mouseup",this.renderCompletion.bind(this,!0)),this.textarea.addEventListener("mouseout",this.renderCompletion.bind(this,!0))),this.createCompletionElement()):this.logError("selector must be pointing to