Edits history of script submission #24070 for ' List events (akips)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    /**
     * List events
     * List event records (status changes, threshold crossings, uptime resets) in a time window, in chronological order. The time filter uses AKIPS syntax, e.g. last1h, today, "from 2026-01-31 08:00 to 2026-01-31 17:00". AKIPS returns all matches at once; limit/offset page through them.
     */
    export async function main(
      auth: RT.Akips,
      time_filter: string,
      event_type: "all" | "critical" | "enum" | "threshold" | "uptime" | undefined,
      device: string | undefined,
      child: string | undefined,
      attribute: string | undefined,
      group: string | undefined,
      limit: number | undefined,
      offset: number | undefined
    ) {
      const tf = time_filter.trim()
      const quotedTf = /\s/.test(tf) && !tf.startsWith('"') ? `"${tf}"` : tf
      let cmd = `mget event ${event_type || "all"} time ${quotedTf}`
      if (device || child || attribute) {
        cmd += ` ${device || "*"} ${child || "*"} ${attribute || "*"}`
      }
      if (group) {
        cmd += ` any group ${group}`
      }
    
      // A line break starts a second api-db command (§4.5.2 data), so inputs must stay on one line.
      if (/[\r\n]/.test(cmd)) throw new Error("api-db command must be a single line")
    
      // Documented form (API guide §4.5.2): password in the URL, commands in the POST body.
      const url = new URL(`${auth.base_url}/api-db`)
      url.searchParams.append("username", auth.username)
      url.searchParams.append("password", auth.password)
      const response = await fetch(url, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: new URLSearchParams({ cmds: cmd }),
      }).catch((e) => {
        // Network errors quote the full URL: drop the query string, which holds the password.
        throw new Error(String(e).replaceAll(url.search, ""))
      })
      const text = await response.text()
      if (!response.ok || text.startsWith("ERROR:")) {
        throw new Error(`${response.status} ${text}`)
      }
    
      // Each line: "{epoch} {parent} {child} {attribute} {type} {flags} {value} [{child description}]"
      // value is the new enum value, the last uptime in seconds, or the threshold rule exceeded.
      const all = []
      for (const line of text.split("\n")) {
        const match = line.match(
          /^(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/
        )
        if (!match) continue
        const [, epoch, parent, childName, attr, type, flags, value, description] =
          match
        all.push({
          time: new Date(Number(epoch) * 1000).toISOString(),
          epoch: Number(epoch),
          device: parent,
          child: childName,
          attribute: attr,
          type,
          flags: flags.split(","),
          value,
          child_description: description || undefined,
        })
      }
    
      const start = offset || 0
      const size = limit || 500
      return {
        total: all.length,
        offset: start,
        limit: size,
        next_offset: start + size < all.length ? start + size : null,
        events: all.slice(start, start + size),
      }
    }
    

    Submitted by hugo989 6 hours ago