Skip to content

Commit

Permalink
feat: add channel,liff,e2ee
Browse files Browse the repository at this point in the history
  • Loading branch information
piloking committed Dec 3, 2024
1 parent 12e1102 commit 7784a77
Show file tree
Hide file tree
Showing 28 changed files with 54,385 additions and 13,987 deletions.
12 changes: 11 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,19 @@
]
},
"imports": {
"@std/assert": "jsr:@std/assert@^1.0.2"
"@std/assert": "jsr:@std/assert@^1.0.2",
"curve25519-js": "npm:curve25519-js@^0.0.4",
"node-bignumber": "npm:node-bignumber@^1.2.2",
"thrift": "npm:thrift@^0.20.0",
"tweetnacl": "npm:tweetnacl@^1.0.3",
"jsdom": "npm:jsdom@25.0.0",
"node-types": "npm:@types/node@latest",
"node-int64": "npm:node-int64@^0.4.0"
},
"nodeModulesDir": "auto",
"compilerOptions": {
"types": ["node-types"]
},
"tasks": {
"dev": "deno run -A --watch sandbox/main.ts"
}
Expand Down
70 changes: 65 additions & 5 deletions packages/linejs/src/core/mod.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,71 @@
import type { Auth } from "../auth/mod.ts";
import { Login } from "../login/mod.ts";
import { Thrift } from "../thrift/mod.ts";
import { RequestClient } from "../request/mod.ts";
import { E2EE } from "../e2ee/mod.ts";
import { type Device, getDeviceDetails } from "./utils/devices.ts";
import { Thrift as def } from "@evex/linejs-types/thrift";
import type * as LINETypes from "@evex/linejs-types";
import { type BaseStorage, MemoryStorage } from "../storage/mod.ts";
import { TypedEventEmitter } from "./typed-event-emitter/index.ts";
import type { ClientEvents } from "./utils/events.ts";
import type { Log } from "./utils/events.ts";

export interface ClientInit {
auth: Auth
/**
* version which LINE App to emurating
*/
version?: string;

/**
* API Endpoint
* @default "gw.line.naver.jp"
*/
endpoint?: string;

/**
* Device
*/
device: Device;

/**
* Storage
* @default MemoryStorage
*/
storage?: BaseStorage;
}

export class Client {
export class Client extends TypedEventEmitter<ClientEvents> {
endpoint: string;
device: Device;
authToken?: string;
login: Login;
thrift: Thrift;
request: RequestClient;
storage: BaseStorage;
e2ee: E2EE;
user?: LINETypes.Profile;

timeout: number = 30000;
constructor(init: ClientInit) {

super();
this.endpoint = init.endpoint ?? "gw.line.naver.jp";
const deviceDetails = getDeviceDetails(init.device, init.version);
if (!deviceDetails) {
throw new Error(`Unsupported device: ${init.device}.`);
}
this.storage = init.storage ?? new MemoryStorage();
this.request = new RequestClient({
endpoint: this.endpoint,
client: this,
deviceDetails,
});
this.login = new Login({ client: this });
this.thrift = new Thrift();
this.e2ee = new E2EE({ client: this });
this.thrift.def = def;
this.device = init.device;
}
log(type: string, data: Record<string, any>) {
console.log(type, data);
}
}
}
18 changes: 18 additions & 0 deletions packages/linejs/src/core/typed-event-emitter/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { assertEquals } from "@std/assert";
import { TypedEventEmitter } from "./index.ts";

Deno.test("promise() should be vaild", async () => {
type Events = {
example: (v: number) => void;
};
class Client extends TypedEventEmitter<Events, "example"> {}
const client = new Client();

const promise = client.waitFor("example");

client.emit("example", 123456);

const [v] = await promise;

assertEquals(v, 123456);
});
58 changes: 58 additions & 0 deletions packages/linejs/src/core/typed-event-emitter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { LooseType } from "../../entities/common.ts";

type RecordEvent = Record<string, (...args: LooseType[]) => LooseType>;

export class TypedEventEmitter<
T extends RecordEvent,
E extends keyof T = keyof T,
> {
public listeners: Map<E, T[E][]> = new Map();

public on<E2 extends E>(event: E2, ...listeners: T[E2][]): this {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}

for (const listener of listeners) {
this.listeners.get(event)?.push(listener);
}

return this;
}

public off<E2 extends E>(event: E2, ...listeners: T[E2][]): this {
if (this.listeners.has(event)) {
for (const listener of listeners) {
if (!this.listeners.get(event)?.includes(listener)) continue;

this.listeners
.get(event)
?.splice(this.listeners.get(event)?.indexOf(listener) ?? 0, 1);
}
}

return this;
}

public emit<E2 extends E>(event: E2, ...args: Parameters<T[E2]>): this {
if (this.listeners.has(event)) {
this.listeners.get(event)?.forEach((listener) => listener(...args));
}

return this;
}

/**
* This creates a promise that you can use for a single event.
* @param event A event name
*/
public waitFor<E2 extends E, P = Parameters<T[E2]>>(event: E2): Promise<P> {
return new Promise<P>((resolve) => {
const listener = ((...args) => {
this.off(event, listener);
resolve(args as P);
}) as T[E2];
this.on(event, listener);
});
}
}
11 changes: 11 additions & 0 deletions packages/linejs/src/core/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Client } from "./mod.ts";
export interface ClientInitBase {
/**
* Client
*/
client: Client;
}
export type fetchLike = (
input: Request | URL | string,
init?: RequestInit,
) => Promise<Response>;
23 changes: 11 additions & 12 deletions packages/linejs/src/core/utils/devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ export type Device =
| "WEAROS";

export interface DeviceDetails {
device: Device;
appVersion: string;
systemName: string;
systemVersion: string;
}

export type DeviceMap = Partial<Record<Device, string>>;

export function getDeviceDetails(
device: Device,
deviceMap: DeviceMap,
version?: string,
): DeviceDetails | null {
let appVersion;
let systemName;
Expand All @@ -27,12 +26,12 @@ export function getDeviceDetails(

switch (device) {
case "DESKTOPWIN":
appVersion = deviceMap[device]||"9.2.0.3403";
appVersion = version || "9.2.0.3403";
systemName = "WINDOWS";
systemVersion = "10.0.0-NT-x64";
break;
case "DESKTOPMAC":
appVersion = deviceMap[device]||"9.2.0.3402";
appVersion = version || "9.2.0.3402";
systemName = "MAC";
break;
/*
Expand All @@ -43,28 +42,28 @@ export function getDeviceDetails(
break;
*/
case "ANDROID":
appVersion = deviceMap[device]||"13.4.1";
appVersion = version || "13.4.1";
systemName = "Android OS";
break;
case "IOS":
appVersion = appVersion = deviceMap[device]||"13.3.0";
appVersion = appVersion = version || "13.3.0";
systemName = "iOS";
break;
case "IOSIPAD":
appVersion = deviceMap[device]||"13.3.0";
appVersion = version || "13.3.0";
systemName = "iOS";
break;
case "WATCHOS":
appVersion = deviceMap[device]||"13.3.0";
appVersion = version || "13.3.0";
systemName = "Watch OS";
break;
case "WEAROS":
appVersion = deviceMap[device]||"13.4.1";
appVersion = version || "13.4.1";
systemName = "Wear OS";
break;
default:
return null;
}

return { appVersion, systemName, systemVersion };
}
return { device, appVersion, systemName, systemVersion };
}
11 changes: 11 additions & 0 deletions packages/linejs/src/core/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export class InternalError extends Error {
constructor(
readonly type: string,
override readonly message: string,
readonly data: Record<string, any> = {},
) {
super(message);
this.name = type;
this.data = data;
}
}
25 changes: 25 additions & 0 deletions packages/linejs/src/core/utils/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type * as LINETypes from "@evex/linejs-types";
type LogType = "login" | "request" | "response" | (string & {});

export interface Log {
type: LogType;
data: any;
}

export type ClientEvents = {
pincall: (pincode: string) => void;
qrcall: (loginUrl: string) => void;
ready: (user: LINETypes.Profile) => void;
end: (user: LINETypes.Profile) => void;
"update:authToken": (authToken: string) => void;
"update:profile": (profile: LINETypes.Profile) => void;
"update:cert": (cert: string) => void;
"update:qrcert": (qrCert: string) => void;
log: (data: Log) => void;
//"square:message": (squareMessage: SquareMessage) => void;
//"square:status": (squareStatus: SquaerStatus) => void;
"square:event": (squareEvent: LINETypes.SquareEvent) => void;
//message: (message: Message) => void;
// TODO: Add more as square
//event: (talkEvent: LINETypes.Operation) => void;
};
Loading

0 comments on commit 7784a77

Please sign in to comment.