Skip to content

Commit 67e8ab4

Browse files
committed
feat: implement Asterisk Manager Interface (AMI) client with core functionality including actions, events, and responses
1 parent 5eb16b9 commit 67e8ab4

19 files changed

+938
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"dist"
1010
],
1111
"scripts": {
12-
"build": "tsup"
12+
"build": "tsup",
13+
"watch": "tsup --watch"
1314
},
1415
"keywords": [
1516
"asterisk",

src/action.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Message } from "./message";
2+
3+
/**
4+
* Action ID generator function.
5+
* Implements a closure to maintain a sequential counter for generating unique Action IDs.
6+
* Ensures each action sent to Asterisk AMI has a unique identifier.
7+
*/
8+
const ActionUniqueId = (function () {
9+
let nextId = 0;
10+
return function () {
11+
return nextId++;
12+
};
13+
})();
14+
15+
/**
16+
* Base action class for all AMI actions.
17+
* Represents a command to be sent to the Asterisk Manager Interface.
18+
* Every action sent to AMI extends this class to implement specific AMI operations.
19+
* Automatically assigns a unique ActionID to each instance for tracking responses.
20+
*
21+
* @extends Message
22+
*/
23+
export class Action extends Message {
24+
/** ActionID field for AMI - string representation of the ID */
25+
ActionID!: string;
26+
/** Internal unique identifier for tracking */
27+
protected id: number;
28+
/** The name of the action to be performed by AMI */
29+
protected Action!: string;
30+
31+
/**
32+
* Creates a new Action with the specified name.
33+
* Automatically assigns a unique Action ID.
34+
*
35+
* @param {String} name - The action name (e.g., "Login", "Status", "Ping")
36+
*/
37+
constructor(name: string) {
38+
super();
39+
this.id = ActionUniqueId();
40+
this.ActionID = String(this.id);
41+
this.Action = name;
42+
}
43+
}

src/actions/CoreShowChannels.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* CoreShowChannels Action for listing all active channels.
5+
* Provides detailed information about all currently active channels in the system.
6+
*
7+
* @extends Action
8+
*/
9+
export class CoreShowChannels extends Action {
10+
/**
11+
* Creates a new CoreShowChannels action.
12+
*/
13+
constructor() {
14+
super("CoreShowChannels");
15+
}
16+
}

src/actions/CustomAction.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* CustomAction for executing arbitrary AMI actions.
5+
* Allows dynamic creation of any AMI action not explicitly defined as a class.
6+
*
7+
* @extends Action
8+
*/
9+
export class CustomAction extends Action {
10+
/**
11+
* Creates a new custom AMI action with the specified name and parameters.
12+
*
13+
* @param {Object} options - Action configuration
14+
* @param {string} options.name - The name of the AMI action
15+
* @param {Record<string, string | number | boolean>} [options.params] - Optional parameters for the action
16+
*/
17+
constructor({
18+
name,
19+
params,
20+
}: {
21+
name: string;
22+
params?: Record<string, any>;
23+
}) {
24+
super(name);
25+
if (params) {
26+
Object.assign(this, params);
27+
}
28+
}
29+
}

src/actions/Hangup.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* Hangup Action for terminating an active channel.
5+
* Allows administrative termination of calls in progress.
6+
*
7+
* @extends Action
8+
*/
9+
export class Hangup extends Action {
10+
/** The name of the channel to hang up */
11+
protected Channel: string;
12+
/** The numeric hangup cause. */
13+
protected Cause?: string;
14+
15+
/**
16+
* Creates a new Hangup action.
17+
*
18+
* @param {string} channel - The name of the channel to hang up
19+
* @param {string} cause - The numeric hangup cause (e.g., "16" for Normal Clearing, "17" for User Busy)
20+
*/
21+
constructor(channel: string, cause?: string) {
22+
super("Hangup");
23+
this.Channel = channel;
24+
this.Cause = cause;
25+
}
26+
}

src/actions/Login.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* Login Action for authenticating with the Asterisk Manager Interface.
5+
* Required as the first action when establishing a new AMI session.
6+
*
7+
* @extends Action
8+
*/
9+
export class Login extends Action {
10+
/** Username for authentication with AMI */
11+
protected readonly Username: string;
12+
/** Password for authentication with AMI */
13+
protected readonly Secret: string;
14+
15+
/**
16+
* Creates a new Login action with the specified credentials.
17+
*
18+
* @param {string} username - AMI username
19+
* @param {string} secret - AMI password or secret
20+
*/
21+
constructor(username: string, secret: string) {
22+
super("Login");
23+
this.Username = username;
24+
this.Secret = secret;
25+
}
26+
}

src/actions/Logoff.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* Logoff Action for terminating an AMI session.
5+
* Closes the manager connection and stops event generation.
6+
*
7+
* @extends Action
8+
*/
9+
export class Logoff extends Action {
10+
/**
11+
* Creates a new Logoff action.
12+
*/
13+
constructor() {
14+
super("Logoff");
15+
}
16+
}

src/actions/Ping.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* Ping Action for testing connectivity with the Asterisk server.
5+
* Useful for keeping the connection alive and verifying server responsiveness.
6+
*
7+
* @extends Action
8+
*/
9+
export class Ping extends Action {
10+
/**
11+
* Creates a new Ping action.
12+
*/
13+
constructor() {
14+
super("Ping");
15+
}
16+
}

src/actions/Status.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Action } from "../action";
2+
3+
/**
4+
* Status Action for obtaining detailed information about channels.
5+
* When used without a channel parameter, returns information on all active channels.
6+
* When specified with a channel, returns detailed status for only that channel.
7+
*
8+
* @extends Action
9+
*/
10+
export class Status extends Action {
11+
/** Optional channel name to get status for (omit for all channels) */
12+
protected readonly Channel?: string;
13+
/** Optional variables to include in the response */
14+
protected readonly Variables?: string;
15+
/** Optional flag to include all variables */
16+
protected readonly AllVariables?: boolean;
17+
18+
/**
19+
* Creates a new Status action.
20+
*
21+
* @param {string} channel - The name of the channel to get status for
22+
* @param {string[]} variables - The variables to include in the response
23+
* @param {boolean} allVariables - Whether to include all variables
24+
*/
25+
constructor(channel?: string, variables?: string[], allVariables?: boolean) {
26+
super("Status");
27+
28+
if (channel) this.Channel = channel;
29+
if (variables) this.Variables = variables.join(",");
30+
31+
if (allVariables !== undefined) this.AllVariables = !!allVariables;
32+
}
33+
}

src/actions/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export { Logoff } from "./Logoff";
2+
export { Login } from "./Login";
3+
export { Ping } from "./Ping";
4+
export { CoreShowChannels } from "./CoreShowChannels";
5+
export { Status } from "./Status";
6+
export { Hangup } from "./Hangup";
7+
export { CustomAction } from "./CustomAction";

0 commit comments

Comments
 (0)