Files
haos_config/www/community/advanced-camera-card/engine-frigate-c3dcf0c3.js
2026-01-30 23:31:00 -06:00

4 lines
27 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{dU as e,eq as t,er as n,es as a,et as r,eu as i,l as s,ev as o,ew as c,d$ as g,dj as u,ex as l,ek as m,k as f,ey as d,ez as h,dz as _,i as p,e2 as y,eA as b,ds as w,dY as D,dX as C,eB as T,eC as v,eD as I,ef as S,j as M,d_ as F,e0 as $}from"./card-b98d578d.js";import{C as z}from"./engine-86b0096c.js";import{C as E,g as N,a as R,b as Y,G as x}from"./engine-generic-75ad9390.js";import{s as H,e as j}from"./startOfHour-a87a7c0b.js";import"./live-provider-845afb16.js";function U(t){return e(1e3*t)}const Z=n.object({camera:n.string(),end_time:n.number().nullable(),false_positive:n.boolean().nullable(),has_clip:n.boolean(),has_snapshot:n.boolean(),id:n.string(),label:n.string(),sub_label:n.string().nullable(),start_time:n.number(),top_score:n.number().nullable(),zones:n.string().array(),retain_indefinitely:n.boolean().optional()}).array(),q=n.object({hour:n.preprocess((e=>Number(e)),n.number().min(0).max(23)),duration:n.number().min(0),events:n.number().min(0)}),W=n.object({day:n.preprocess((e=>"string"==typeof e?a(e):e),n.date()),events:n.number(),hours:q.array()}).array(),A=n.object({start_time:n.number(),end_time:n.number(),id:n.string()}).array(),P=n.object({success:n.boolean(),message:n.string()}),Q=n.object({camera:n.string(),day:n.string(),label:n.string(),sub_label:n.string().nullable(),zones:n.string().array()}).array(),k=n.object({name:n.string().optional(),features:n.string().array().optional(),presets:n.string().array().optional()}),O=n.object({camera:n.string(),snapshot:n.object({frame_time:n.number()}).nullable(),has_clip:n.boolean(),has_snapshot:n.boolean(),label:n.string(),current_zones:n.string().array()}),G=n.object({before:O,after:O,type:n.enum(["new","update","end"])});const L=async(e,t)=>await r(e,Z,{type:"frigate/events/get",...t},!0),V=e=>"birdseye"===e.frigate.camera_name;class J extends E{constructor(){super(...arguments),this._frigateEventHandler=e=>{const t=!e.before.has_snapshot&&e.after.has_snapshot||e.before.snapshot?.frame_time!==e.after.snapshot?.frame_time,n=!e.before.has_clip&&e.after.has_clip,a=this.getConfig(),r=this._config.id;if(!r)return;if(a.frigate.zones?.length&&!a.frigate.zones.some((t=>e.after.current_zones.includes(t)))||a.frigate.labels?.length&&!a.frigate.labels.includes(e.after.label))return;const i=a.triggers.events;(i.includes("events")||i.includes("snapshots")&&t||i.includes("clips")&&n)&&this._eventCallback?.({cameraID:r,fidelity:"high",type:e.type,clip:n&&i.includes("clips"),snapshot:t&&i.includes("snapshots")})}}async initialize(e){return await this._initializeConfig(e.hass,e.entityRegistryManager),await super.initialize(e),this._capabilities?.has("trigger")&&await this._subscribeToEvents(e.hass,e.frigateEventWatcher),this}async executePTZAction(e,t,n){if(await super.executePTZAction(e,t,n))return!0;const a=this.getConfig().camera_entity;return!("preset"===t&&!n?.preset||!a)&&(await e.executeActions({actions:{action:"perform-action",perform_action:"frigate.ptz",data:{action:"stop"===n?.phase?"stop":"zoom_in"===t||"zoom_out"===t?"zoom":"preset"===t?"preset":"move",..."stop"!==n?.phase&&{argument:"zoom_in"===t?"in":"zoom_out"===t?"out":"preset"===t?n?.preset:t}},target:{entity_id:a}}}),!0)}async _initializeConfig(e,n){const a=this.getConfig(),r=!!a.frigate?.camera_name,i=a.triggers.motion||a.triggers.occupancy;let g=null;const u=o(a);if(u&&(!r||i)&&(g=await n.getEntity(e,u),!g))throw new c(s("error.no_camera_entity"),a);if(g&&!r){const e=this._getFrigateCameraNameFromEntity(g);e&&(this._config.frigate.camera_name=e)}if(i){const r=await n.getMatchingEntities(e,(e=>e.config_entry_id===g?.config_entry_id&&!e.disabled_by&&e.entity_id.startsWith("binary_sensor.")));if(a.triggers.motion){const e=this._getMotionSensor(a,[...r.values()]);e&&a.triggers.entities.push(e)}if(a.triggers.occupancy){const e=this._getOccupancySensor(a,[...r.values()]);e&&a.triggers.entities.push(...e)}a.triggers.entities=(l=a.triggers.entities)&&l.length?t(l):[]}var l}async _getRawCapabilities(e){const t=await super._getRawCapabilities(e),n=this.getConfig(),a=await this._getPTZCapabilities(e.hass,n),r=N(n),i=r||a?{...a,...r}:null,s=V(n);return{...t,"favorite-events":!s,seek:!s,clips:!s,snapshots:!s,recordings:!s,...i&&{ptz:i}}}_getFrigateCameraNameFromEntity(e){if("frigate"===e.platform&&e.unique_id&&"string"==typeof e.unique_id){const t=e.unique_id.match(/:camera:(?<camera>[^:]+)$/);if(t&&t.groups)return t.groups.camera}return null}getEndpoints(e){const t=super.getEndpoints(e),n=this._getJSMPEGEndpoint();return t||n?{...t,...n&&{jsmpeg:n}}:null}_getGo2RTCMetadataEndpoint(){const e=this._config.go2rtc?.stream??this._config.frigate.camera_name,t=this._config.go2rtc?.url??`/api/frigate/${this._config.frigate.client_id}/go2rtc`;return R(this._config,{url:t,stream:e})}_getGo2RTCStreamEndpoint(){const e=this._config.go2rtc?.stream??this._config.frigate.camera_name,t=this._config.go2rtc?.url??`/api/frigate/${this._config.frigate.client_id}/mse`;return Y(this._config,{url:t,stream:e})}_getJSMPEGEndpoint(){return this._config.frigate.camera_name?{endpoint:`/api/frigate/${this._config.frigate.client_id}/jsmpeg/${this._config.frigate.camera_name}`,sign:!0}:null}_getUIEndpoint(e){if(!this._config.frigate.url)return null;if(!this._config.frigate.camera_name)return{endpoint:this._config.frigate.url};const t=`${this._config.frigate.url}/#${this._config.frigate.camera_name}`;if("live"===e?.view)return{endpoint:t};const n=`${this._config.frigate.url}/events?camera=${this._config.frigate.camera_name}`,a=`${this._config.frigate.url}/recording/${this._config.frigate.camera_name}`;switch(e?.media?.getMediaType()){case"clip":case"snapshot":return{endpoint:n};case"recording":const t=e.media.getStartTime();return{endpoint:a+(t?"/"+g(t,"yyyy-MM-dd/HH"):"")}}switch(e?.view){case"clip":case"clips":case"snapshots":case"snapshot":return{endpoint:n};case"recording":case"recordings":return{endpoint:a}}return{endpoint:t}}async _getPTZCapabilities(e,t){if(!t.frigate.camera_name||V(t))return null;let n=null;try{n=await(async(e,t,n)=>await r(e,k,{type:"frigate/ptz/info",instance_id:t,camera:n},!0))(e,t.frigate.client_id,t.frigate.camera_name)}catch(e){return u(e),null}const a=[...n.features?.includes("pt")?[l.Continuous]:[]],i=[...n.features?.includes("zoom")?[l.Continuous]:[]],s=n.presets;return a.length||i.length||s?.length?{...a.length&&{left:a,right:a,up:a,down:a},...i.length&&{zoomIn:i,zoomOut:i},...s?.length&&{presets:s}}:null}_getMotionSensor(e,t){return e.frigate.camera_name?t.find((t=>"string"==typeof t.unique_id&&!!t.unique_id?.match(new RegExp(`:motion_sensor:${e.frigate.camera_name}`))))?.entity_id??null:null}_getOccupancySensor(e,t){const n=[],a=(e,a)=>{const r=t.find((t=>"string"==typeof t.unique_id&&!!t.unique_id?.match(new RegExp(`:occupancy_sensor:${e}_${a}`))))?.entity_id??null;r&&n.push(r)};if(e.frigate.camera_name){const t=e.frigate.zones?.length?e.frigate.zones:[e.frigate.camera_name],r=e.frigate.labels?.length?e.frigate.labels:["all"];for(const e of t)for(const t of r)a(e,t);if(n.length)return n}return null}async _subscribeToEvents(e,t){const n=this.getConfig();if(!n.triggers.events.length||!n.frigate.camera_name)return;
/* istanbul ignore next -- exercising the matcher is not possible when the
test uses an event watcher -- @preserve */const a={instanceID:n.frigate.client_id,callback:e=>this._frigateEventHandler(e),matcher:e=>e.after.camera===n.frigate.camera_name};await t.subscribe(e,a),this._onDestroy((()=>t.unsubscribe(a)))}}class B{constructor(){this._requests=[],this._unsubscribeCallback={}}async subscribe(e,t){const n=!this._hasSubscribers(t.instanceID);this._requests.push(t),n&&(this._unsubscribeCallback[t.instanceID]=await e.connection.subscribeMessage((e=>this._receiveHandler(t.instanceID,e)),{type:"frigate/events/subscribe",instance_id:t.instanceID}))}async unsubscribe(e){this._requests=this._requests.filter((t=>t!==e)),this._hasSubscribers(e.instanceID)||(await this._unsubscribeCallback[e.instanceID](),delete this._unsubscribeCallback[e.instanceID])}_hasSubscribers(e){return!!this._requests.filter((t=>t.instanceID===e)).length}_receiveHandler(e,t){let n;try{n=JSON.parse(t)}catch(e){return void console.warn("Received non-JSON payload as Frigate event",t)}const a=G.safeParse(n);if(a.success)for(const t of this._requests)t.instanceID!==e||t.matcher&&!t.matcher(a.data)||t.callback(a.data);else console.warn("Received malformed Frigate event from Home Assistant",t)}}function K(e,t){const n=function(e){if(!ee[e]){const t=new Intl.DateTimeFormat("en-US",{hourCycle:"h23",timeZone:"America/New_York",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).format(new Date("2014-06-25T04:00:00.123Z")),n="06/25/2014, 00:00:00"===t||"06/25/2014 00:00:00"===t;ee[e]=n?new Intl.DateTimeFormat("en-US",{hourCycle:"h23",timeZone:e,year:"numeric",month:"numeric",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}):new Intl.DateTimeFormat("en-US",{hour12:!1,timeZone:e,year:"numeric",month:"numeric",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})}return ee[e]}(t);return"formatToParts"in n?function(e,t){try{const n=e.formatToParts(t),a=[];for(let e=0;e<n.length;e++){const t=X[n[e].type];void 0!==t&&(a[t]=parseInt(n[e].value,10))}return a}catch(e){if(e instanceof RangeError)return[NaN];throw e}}(n,e):function(e,t){const n=e.format(t),a=/(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(n);return[parseInt(a[3],10),parseInt(a[1],10),parseInt(a[2],10),parseInt(a[4],10),parseInt(a[5],10),parseInt(a[6],10)]}(n,e)}const X={year:0,month:1,day:2,hour:3,minute:4,second:5};const ee={};function te(e,t,n,a,r,i,s){const o=new Date(0);return o.setUTCFullYear(e,t,n),o.setUTCHours(a,r,i,s),o}const ne=36e5,ae=6e4,re={timezone:/([Z+-].*)$/,timezoneZ:/^(Z)$/,timezoneHH:/^([+-]\d{2})$/,timezoneHHMM:/^([+-])(\d{2}):?(\d{2})$/};function ie(e,t,n){if(!e)return 0;let a,r,i=re.timezoneZ.exec(e);if(i)return 0;if(i=re.timezoneHH.exec(e),i)return a=parseInt(i[1],10),oe(a)?-a*ne:NaN;if(i=re.timezoneHHMM.exec(e),i){a=parseInt(i[2],10);const e=parseInt(i[3],10);return oe(a,e)?(r=Math.abs(a)*ne+e*ae,"+"===i[1]?-r:r):NaN}if(function(e){if(ce[e])return!0;try{return new Intl.DateTimeFormat(void 0,{timeZone:e}),ce[e]=!0,!0}catch(e){return!1}}(e)){t=new Date(t||Date.now());const a=n?t:function(e){return te(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds())}(t),r=se(a,e),i=n?r:function(e,t,n){const a=e.getTime();let r=a-t;const i=se(new Date(r),n);if(t===i)return t;r-=i-t;const s=se(new Date(r),n);if(i===s)return i;return Math.max(i,s)}(t,r,e);return-i}return NaN}function se(e,t){const n=K(e,t),a=te(n[0],n[1]-1,n[2],n[3]%24,n[4],n[5],0).getTime();let r=e.getTime();const i=r%1e3;return r-=i>=0?i:1e3+i,a-r}function oe(e,t){return-23<=e&&e<=23&&(null==t||0<=t&&t<=59)}const ce={};function ge(e){const t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return t.setUTCFullYear(e.getFullYear()),+e-+t}const ue=36e5,le=6e4,me=2,fe={dateTimePattern:/^([0-9W+-]+)(T| )(.*)/,datePattern:/^([0-9W+-]+)(.*)/,plainTime:/:/,YY:/^(\d{2})$/,YYY:[/^([+-]\d{2})$/,/^([+-]\d{3})$/,/^([+-]\d{4})$/],YYYY:/^(\d{4})/,YYYYY:[/^([+-]\d{4})/,/^([+-]\d{5})/,/^([+-]\d{6})/],MM:/^-(\d{2})$/,DDD:/^-?(\d{3})$/,MMDD:/^-?(\d{2})-?(\d{2})$/,Www:/^-?W(\d{2})$/,WwwD:/^-?W(\d{2})-?(\d{1})$/,HH:/^(\d{2}([.,]\d*)?)$/,HHMM:/^(\d{2}):?(\d{2}([.,]\d*)?)$/,HHMMSS:/^(\d{2}):?(\d{2}):?(\d{2}([.,]\d*)?)$/,timeZone:/(Z|[+-]\d{2}(?::?\d{2})?| UTC| [a-zA-Z]+\/[a-zA-Z_]+(?:\/[a-zA-Z_]+)?)$/};function de(e,t={}){if(arguments.length<1)throw new TypeError("1 argument required, but only "+arguments.length+" present");if(null===e)return new Date(NaN);const n=null==t.additionalDigits?me:Number(t.additionalDigits);if(2!==n&&1!==n&&0!==n)throw new RangeError("additionalDigits must be 0, 1 or 2");if(e instanceof Date||"object"==typeof e&&"[object Date]"===Object.prototype.toString.call(e))return new Date(e.getTime());if("number"==typeof e||"[object Number]"===Object.prototype.toString.call(e))return new Date(e);if("[object String]"!==Object.prototype.toString.call(e))return new Date(NaN);const a=function(e){const t={};let n,a=fe.dateTimePattern.exec(e);a?(t.date=a[1],n=a[3]):(a=fe.datePattern.exec(e),a?(t.date=a[1],n=a[2]):(t.date=null,n=e));if(n){const e=fe.timeZone.exec(n);e?(t.time=n.replace(e[1],""),t.timeZone=e[1].trim()):t.time=n}return t}(e),{year:r,restDateString:i}=function(e,t){if(e){const n=fe.YYY[t],a=fe.YYYYY[t];let r=fe.YYYY.exec(e)||a.exec(e);if(r){const t=r[1];return{year:parseInt(t,10),restDateString:e.slice(t.length)}}if(r=fe.YY.exec(e)||n.exec(e),r){const t=r[1];return{year:100*parseInt(t,10),restDateString:e.slice(t.length)}}}return{year:null}}(a.date,n),s=function(e,t){if(null===t)return null;let n,a,r;if(!e||!e.length)return n=new Date(0),n.setUTCFullYear(t),n;let i=fe.MM.exec(e);if(i)return n=new Date(0),a=parseInt(i[1],10)-1,be(t,a)?(n.setUTCFullYear(t,a),n):new Date(NaN);if(i=fe.DDD.exec(e),i){n=new Date(0);const e=parseInt(i[1],10);return function(e,t){if(t<1)return!1;const n=ye(e);if(n&&t>366)return!1;if(!n&&t>365)return!1;return!0}(t,e)?(n.setUTCFullYear(t,0,e),n):new Date(NaN)}if(i=fe.MMDD.exec(e),i){n=new Date(0),a=parseInt(i[1],10)-1;const e=parseInt(i[2],10);return be(t,a,e)?(n.setUTCFullYear(t,a,e),n):new Date(NaN)}if(i=fe.Www.exec(e),i)return r=parseInt(i[1],10)-1,we(r)?he(t,r):new Date(NaN);if(i=fe.WwwD.exec(e),i){r=parseInt(i[1],10)-1;const e=parseInt(i[2],10)-1;return we(r,e)?he(t,r,e):new Date(NaN)}return null}(i,r);if(null===s||isNaN(s.getTime()))return new Date(NaN);if(s){const e=s.getTime();let n,r=0;if(a.time&&(r=function(e){let t,n,a=fe.HH.exec(e);if(a)return t=parseFloat(a[1].replace(",",".")),De(t)?t%24*ue:NaN;if(a=fe.HHMM.exec(e),a)return t=parseInt(a[1],10),n=parseFloat(a[2].replace(",",".")),De(t,n)?t%24*ue+n*le:NaN;if(a=fe.HHMMSS.exec(e),a){t=parseInt(a[1],10),n=parseInt(a[2],10);const e=parseFloat(a[3].replace(",","."));return De(t,n,e)?t%24*ue+n*le+1e3*e:NaN}return null}(a.time),null===r||isNaN(r)))return new Date(NaN);if(a.timeZone||t.timeZone){if(n=ie(a.timeZone||t.timeZone,new Date(e+r)),isNaN(n))return new Date(NaN)}else n=ge(new Date(e+r)),n=ge(new Date(e+r+n));return new Date(e+r+n)}return new Date(NaN)}function he(e,t,n){t=t||0,n=n||0;const a=new Date(0);a.setUTCFullYear(e,0,4);const r=7*t+n+1-(a.getUTCDay()||7);return a.setUTCDate(a.getUTCDate()+r),a}const _e=[31,28,31,30,31,30,31,31,30,31,30,31],pe=[31,29,31,30,31,30,31,31,30,31,30,31];function ye(e){return e%400==0||e%4==0&&e%100!=0}function be(e,t,n){if(t<0||t>11)return!1;if(null!=n){if(n<1)return!1;const a=ye(e);if(a&&n>pe[t])return!1;if(!a&&n>_e[t])return!1}return!0}function we(e,t){return!(e<0||e>52)&&(null==t||!(t<0||t>6))}function De(e,t,n){return!(e<0||e>=25)&&((null==t||!(t<0||t>=60))&&(null==n||!(n<0||n>=60)))}const Ce=e=>{const t=Intl.DateTimeFormat().resolvedOptions().timeZone,n=Math.round(e.end_time?e.end_time-e.start_time:Date.now()/1e3-e.start_time),a=null!==e.top_score?` ${Math.round(100*e.top_score)}%`:"";return`${m(function(e,t,n){const a=ie(t,e=de(e,n),!0),r=new Date(e.getTime()-a),i=new Date(0);return i.setFullYear(r.getUTCFullYear(),r.getUTCMonth(),r.getUTCDate()),i.setHours(r.getUTCHours(),r.getUTCMinutes(),r.getUTCSeconds(),r.getUTCMilliseconds()),i}(1e3*e.start_time,t))} [${n}s, ${f(e.label)}${a}]`};class Te extends h{constructor(e,t,n,a,r,i){super(e,{cameraID:t}),this._event=n,this._contentID=a,this._thumbnail=r,this._subLabels=i??null}getStartTime(){return U(this._event.start_time)}getEndTime(){return this._event.end_time?U(this._event.end_time):null}inProgress(){return!this.getEndTime()}getVideoContentType(){return _.HLS}getID(){return this._event.id}getContentID(){return this._contentID}getTitle(){return Ce(this._event)}getThumbnail(){return this._thumbnail}isFavorite(){return this._event.retain_indefinitely??null}setFavorite(e){this._event.retain_indefinitely=e}getWhat(){return[this._event.label]}getWhere(){const e=this._event.zones;return e.length?e:null}getScore(){return this._event.top_score}getTags(){return this._subLabels}isGroupableWith(e){return this.getMediaType()===e.getMediaType()&&p(this.getWhere(),e.getWhere())&&p(this.getWhat(),e.getWhat())}}class ve extends h{constructor(e,t,n,a,r,i){super(e,{cameraID:t}),this._recording=n,this._id=a,this._contentID=r,this._title=i}getID(){return this._id}getStartTime(){return this._recording.startTime}getEndTime(){return this._recording.endTime}inProgress(){return!this.getEndTime()}getVideoContentType(){return _.HLS}getContentID(){return this._contentID}getTitle(){return this._title}getEventCount(){return this._recording.events}}class Ie{static createEventViewMedia(e,t,n,a,r){return"clip"===e&&!a.has_clip||"snapshot"===e&&!a.has_snapshot||!n.frigate.client_id||!n.frigate.camera_name?null:new Te(e,t,a,((e,t,n,a)=>`media-source://frigate/${e}/event/${a}/${t}/${n.id}`)(n.frigate.client_id,n.frigate.camera_name,a,"clip"===e?"clips":"snapshots"),((e,t)=>`/api/frigate/${e}/thumbnail/${t.id}`)(n.frigate.client_id,a),r)}static createRecordingViewMedia(e,t,n,a){return n.frigate.client_id&&n.frigate.camera_name?new ve(d.Recording,e,t,((e,t)=>`${e.frigate?.client_id??""}/${e.frigate.camera_name??""}/${t.startTime.getTime()}/${t.endTime.getTime()}`)(n,t),((e,t,n)=>["media-source://frigate",e,"recordings",t,`${n.startTime.getFullYear()}-${String(n.startTime.getMonth()+1).padStart(2,"0")}-${String(String(n.startTime.getDate()).padStart(2,"0"))}`,String(n.startTime.getHours()).padStart(2,"0")].join("/"))(n.frigate.client_id,n.frigate.camera_name,t),((e,t)=>`${e} ${m(t.startTime)}`)(a,t)):null}}class Se{static isFrigateMedia(e){return this.isFrigateEvent(e)||this.isFrigateRecording(e)}static isFrigateEvent(e){return e instanceof Te}static isFrigateRecording(e){return e instanceof ve}}class Me{static isFrigateEventQueryResults(e){return e.engine===b.Frigate&&e.type===I.Event}static isFrigateRecordingQueryResults(e){return e.engine===b.Frigate&&e.type===I.Recording}static isFrigateRecordingSegmentsResults(e){return e.engine===b.Frigate&&e.type===I.RecordingSegments}}class Fe extends x{constructor(e,t,n,a,r){super(t,r),this._throttledSegmentGarbageCollector=y(this._garbageCollectSegments.bind(this),36e5,{leading:!1,trailing:!0}),this._entityRegistryManager=e,this._frigateEventWatcher=new B,this._recordingSegmentsCache=n,this._requestCache=a}getEngineType(){return b.Frigate}async createCamera(e,t){const n=new J(t,this,{eventCallback:this._eventCallback});return await n.initialize({hass:e,entityRegistryManager:this._entityRegistryManager,stateWatcher:this._stateWatcher,frigateEventWatcher:this._frigateEventWatcher})}async getMediaDownloadPath(e,t,n){return Se.isFrigateEvent(n)?{endpoint:`/api/frigate/${t.frigate.client_id}/notifications/${n.getID()}/`+(w.isClip(n)?"clip.mp4":"snapshot.jpg")+"?download=true",sign:!0}:Se.isFrigateRecording(n)?{endpoint:`/api/frigate/${t.frigate.client_id}/recording/${t.frigate.camera_name}/start/${Math.floor(n.getStartTime().getTime()/1e3)}/end/${Math.floor(n.getEndTime().getTime()/1e3)}?download=true`,sign:!0}:null}generateDefaultEventQuery(e,t,n){const a=[...e.getCameraConfigs(t)],r=D(a.map((e=>e?.frigate.zones)),p),i=D(a.map((e=>e?.frigate.labels)),p);if(1===r.length&&1===i.length)return[{type:C.Event,cameraIDs:t,...i[0]&&{what:new Set(i[0])},...r[0]&&{where:new Set(r[0])},...n}];const s=[];for(const a of t){const t=e.getCameraConfig(a);t&&s.push({type:C.Event,cameraIDs:new Set([a]),...t.frigate.labels&&{what:new Set(t.frigate.labels)},...t.frigate.zones&&{where:new Set(t.frigate.zones)},...n})}return s.length?s:null}generateDefaultRecordingQuery(e,t,n){return[{type:C.Recording,cameraIDs:t,...n}]}generateDefaultRecordingSegmentsQuery(e,t,n){return n.start&&n.end?[{type:C.RecordingSegments,cameraIDs:t,start:n.start,end:n.end,...n}]:null}async favoriteMedia(e,t,n,a){Se.isFrigateEvent(n)&&(await async function(e,t,n,a){const o={type:"frigate/event/retain",instance_id:t,event_id:n,retain:a},c=await r(e,P,o,!0);if(!c.success)throw new i(s("error.failed_retain"),{request:o,response:c})}(e,t.frigate.client_id,n.getID(),a),n.setFavorite(a))}_buildInstanceToCameraIDMapFromQuery(e,t){const n=new Map;for(const a of t){const t=this._getQueryableCameraConfig(e,a),r=t?.frigate.client_id;r&&(n.has(r)||n.set(r,new Set),n.get(r)?.add(a))}return n}_getFrigateCameraNamesForCameraIDs(e,t){const n=new Set;for(const a of t){const t=this._getQueryableCameraConfig(e,a);t?.frigate.camera_name&&n.add(t.frigate.camera_name)}return n}async getEvents(e,t,n,a){const r=new Map,i=async(i,s)=>{if(!s||!s.size)return;const o={...n,cameraIDs:s},c=a?.useCache??1?this._requestCache.get(o):null;if(c)return void r.set(n,c);const g={instance_id:i,cameras:Array.from(this._getFrigateCameraNamesForCameraIDs(t,s)),...n.what&&{labels:Array.from(n.what)},...n.where&&{zones:Array.from(n.where)},...n.tags&&{sub_labels:Array.from(n.tags)},...n.end&&{before:Math.floor(n.end.getTime()/1e3)},...n.start&&{after:Math.floor(n.start.getTime()/1e3)},...n.limit&&{limit:n.limit},...n.hasClip&&{has_clip:n.hasClip},...n.hasSnapshot&&{has_snapshot:n.hasSnapshot},...n.favorite&&{favorites:n.favorite},limit:n?.limit??z},u={type:I.Event,engine:b.Frigate,instanceID:i,events:await L(e,g),expiry:S(new Date,{seconds:60}),cached:!1};(a?.useCache??1)&&this._requestCache.set(n,{...u,cached:!0},u.expiry),r.set(o,u)},s=this._buildInstanceToCameraIDMapFromQuery(t,n.cameraIDs);return await Promise.all(Array.from(s.keys()).map((e=>i(e,s.get(e))))),r.size?r:null}async getRecordings(e,t,n,a){const i=new Map,s=async(n,s)=>{const o={...n,cameraIDs:new Set([s])},c=a?.useCache??1?this._requestCache.get(o):null;if(c)return void i.set(o,c);const g=this._getQueryableCameraConfig(t,s);if(!g||!g.frigate.camera_name)return;const u=await(async(e,t,n)=>await r(e,W,{type:"frigate/recordings/summary",instance_id:t,camera:n,timezone:e.config.time_zone},!0))(e,g.frigate.client_id,g.frigate.camera_name);let l=[];for(const e of u??[])for(const t of e.hours){const n=S(e.day,{hours:t.hour}),a=H(n),r=j(n);(!o.start||a>=o.start)&&(!o.end||r<=o.end)&&l.push({cameraID:s,startTime:a,endTime:r,events:t.events})}void 0!==o.limit&&(l=F(l,(e=>e.startTime),"desc").slice(0,o.limit));const m={type:I.Recording,engine:b.Frigate,instanceID:g.frigate.client_id,recordings:l,expiry:S(new Date,{seconds:60}),cached:!1};(a?.useCache??1)&&this._requestCache.set(o,{...m,cached:!0},m.expiry),i.set(o,m)};return await Promise.all(Array.from(n.cameraIDs).map((e=>s(n,e)))),i.size?i:null}async getRecordingSegments(e,t,n,a){const i=new Map,s=async(n,s)=>{const o={...n,cameraIDs:new Set([s])},c=this._getQueryableCameraConfig(t,s);if(!c||!c.frigate.camera_name)return;const g={start:o.start,end:o.end},u=a?.useCache??1?this._recordingSegmentsCache.get(s,g):null;if(u)return void i.set(o,{type:I.RecordingSegments,engine:b.Frigate,instanceID:c.frigate.client_id,segments:u,cached:!0});const l={instance_id:c.frigate.client_id,camera:c.frigate.camera_name,after:Math.floor(o.start.getTime()/1e3),before:Math.floor(o.end.getTime()/1e3)},m=await(async(e,t)=>await r(e,A,{type:"frigate/recordings/get",...t},!0))(e,l);(a?.useCache??1)&&this._recordingSegmentsCache.add(s,g,m),i.set(o,{type:I.RecordingSegments,engine:b.Frigate,instanceID:c.frigate.client_id,segments:m,cached:!1})};return await Promise.all(Array.from(n.cameraIDs).map((e=>s(n,e)))),T((()=>this._throttledSegmentGarbageCollector(e,t))),i.size?i:null}_getCameraIDMatch(e,t,n,a){if(1===t.cameraIDs.size)return[...t.cameraIDs][0];for(const[t,r]of e.getCameraConfigEntries())if(r.frigate.client_id===n&&r.frigate.camera_name===a)return t;return null}generateMediaFromEvents(e,t,n,a){if(!Me.isFrigateEventQueryResults(a))return null;const r=[];for(const e of a.events){const i=this._getCameraIDMatch(t,n,a.instanceID,e.camera);if(!i)continue;const s=this._getQueryableCameraConfig(t,i);if(!s)continue;let o=null;if(n.hasClip||n.hasSnapshot||!e.has_clip&&!e.has_snapshot?n.hasSnapshot&&e.has_snapshot?o=d.Snapshot:n.hasClip&&e.has_clip&&(o=d.Clip):o=e.has_clip?d.Clip:d.Snapshot,!o)continue;const c=Ie.createEventViewMedia(o,i,s,e,e.sub_label?this._splitSubLabels(e.sub_label):void 0);c&&r.push(c)}return r}generateMediaFromRecordings(e,t,n,a){if(!Me.isFrigateRecordingQueryResults(a))return null;const r=[];for(const n of a.recordings){const a=this._getQueryableCameraConfig(t,n.cameraID);if(!a)continue;const i=Ie.createRecordingViewMedia(n.cameraID,n,a,this.getCameraMetadata(e,a).title);i&&r.push(i)}return r}getQueryResultMaxAge(e){return e.type===C.Event||e.type===C.Recording?60:null}async getMediaSeekTime(e,t,n,a,r){const i=n.getStartTime(),s=n.getEndTime(),o=n.getCameraID();if(!i||!s||a<i||a>s||!o)return null;const c={cameraIDs:new Set([o]),start:i,end:s,type:C.RecordingSegments},g=await this.getRecordingSegments(e,t,c,r);return g?this._getSeekTimeInSegments(i,a,Array.from(g.values())[0].segments):null}_getQueryableCameraConfig(e,t){const n=e.getCameraConfig(t);return!n||V(n)?null:n}_splitSubLabels(e){return e.split(",").map((e=>e.trim()))}async getMediaMetadata(e,t,n,a){const i=new Map;if((a?.useCache??1)&&this._requestCache.has(n)){const e=this._requestCache.get(n);if(e)return i.set(n,e),i}const s=new Set,o=new Set,c=new Set,g=new Set,u=this._buildInstanceToCameraIDMapFromQuery(t,n.cameraIDs),l=async(n,a)=>{const i=this._getFrigateCameraNamesForCameraIDs(t,a);for(const t of await(async(e,t)=>await r(e,Q,{type:"frigate/events/summary",instance_id:t,timezone:e.config.time_zone},!0))(e,n))i.has(t.camera)&&(t.label&&s.add(t.label),t.zones.length&&t.zones.forEach(o.add,o),t.day&&c.add(t.day),t.sub_label&&this._splitSubLabels(t.sub_label).forEach(g.add,g))},m=async n=>{const r=await this.getRecordings(e,t,{type:C.Recording,cameraIDs:n},a);if(r)for(const e of r.values())if(Me.isFrigateRecordingQueryResults(e))for(const t of e.recordings)c.add($(t.startTime))};await v([...u.entries()],(([e,t])=>(async()=>{await Promise.all([l(e,t),m(t)])})()));const f={type:I.MediaMetadata,engine:b.Frigate,metadata:{...s.size&&{what:s},...o.size&&{where:o},...c.size&&{days:c},...g.size&&{tags:g}},expiry:S(new Date,{seconds:60}),cached:!1};return(a?.useCache??1)&&this._requestCache.set(n,{...f,cached:!0},f.expiry),i.set(n,f),i}async _garbageCollectSegments(e,t){const n=this._recordingSegmentsCache.getCameraIDs(),a={cameraIDs:new Set(n),type:C.Recording},r=(e,t)=>`${e}/${t.getDate()}/${t.getHours()}`,i=await this.getRecordings(e,t,a);if(i)for(const[e,t]of i){if(!Me.isFrigateRecordingQueryResults(t))continue;const n=new Set;for(const e of t.recordings)n.add(r(e.cameraID,e.startTime));const a=Array.from(e.cameraIDs)[0];this._recordingSegmentsCache.expireMatches(a,(e=>{const t=r(a,U(e.start_time));return!n.has(t)}))}}_getSeekTimeInSegments(e,t,n){if(!n.length)return null;let a=0;for(const r of n){const n=U(r.start_time);if(n>t)break;const i=U(r.end_time),s=n<e?e:n;a+=(i>t?t:i).getTime()-s.getTime()}return a/1e3}getMediaCapabilities(e){return{canFavorite:w.isEvent(e),canDownload:!0}}getCameraMetadata(e,t){return{...super.getCameraMetadata(e,t),title:t.title??M(e,t.camera_entity)??M(e,t.webrtc_card?.entity)??f(t.frigate?.camera_name)??t.id??"",engineIcon:"frigate"}}}export{Fe as FrigateCameraManagerEngine};