anotalkjs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/index.js +181 -0
  3. package/package.json +23 -0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ anotalkjs
package/index.js ADDED
@@ -0,0 +1,181 @@
1
+ import io from "socket.io-client";
2
+ import EventEmitter from "events";
3
+
4
+ /**
5
+ * @typedef {Object} PartnerData
6
+ * @property {string} partner_gender
7
+ * @property {string} chatId
8
+ * @property {string} uid
9
+ */
10
+
11
+ /**
12
+ * Anotalk Client
13
+ */
14
+ export default class Anotalk extends EventEmitter {
15
+ constructor() {
16
+ super();
17
+ this.url = "wss://rfsrv.anotalk.hu:80";
18
+ this.socket = null;
19
+
20
+ this.isConnected = false;
21
+ this.isChatting = false;
22
+ this.isSearching = false;
23
+ this.partner = null;
24
+
25
+ this._searchResolver = null;
26
+ this._searchRejecter = null;
27
+ }
28
+
29
+ /**
30
+ * Connects to the Anotalk server.
31
+ * Automatically called by search() if not already connected.
32
+ * @returns {Promise<void>}
33
+ */
34
+ connect() {
35
+ return new Promise((resolve, reject) => {
36
+ if (this.socket && this.socket.connected) {
37
+ return resolve();
38
+ }
39
+
40
+ this.socket = io(this.url, {
41
+ transports: ["websocket"],
42
+ reconnection: true
43
+ });
44
+
45
+ this.socket.on("connect", () => {
46
+ this.isConnected = true;
47
+ this.emit("connect");
48
+ resolve();
49
+ });
50
+
51
+ this.socket.on("disconnect", (reason) => {
52
+ this.isConnected = false;
53
+ this.isChatting = false;
54
+ this.isSearching = false;
55
+ this.emit("disconnect", reason);
56
+ });
57
+
58
+ this.socket.on("connect_error", (error) => {
59
+ this.emit("error", error);
60
+ if (!this.isConnected) reject(error);
61
+ });
62
+
63
+ this._bindProtocolEvents();
64
+ });
65
+ }
66
+
67
+ /**
68
+ * Internal: Binds socket events to class methods
69
+ */
70
+ _bindProtocolEvents() {
71
+ this.socket.on("onStatistics", (data) => this.emit("statistics", data));
72
+
73
+ this.socket.on("onSearchingPartner", (data) => {
74
+ this.isSearching = true;
75
+ this.isChatting = false;
76
+ this.emit("searching", data);
77
+ });
78
+
79
+ this.socket.on("onChatStart", (data) => {
80
+ this.isSearching = false;
81
+ this.isChatting = true;
82
+ this.partner = data;
83
+
84
+ if (this._searchResolver) {
85
+ this._searchResolver(data);
86
+ this._searchResolver = null;
87
+ this._searchRejecter = null;
88
+ }
89
+
90
+ this.emit("chatStart", data);
91
+ });
92
+
93
+ this.socket.on("onTyping", () => this.emit("partnerTyping"));
94
+ this.socket.on("onDoneTyping", () => this.emit("partnerDoneTyping"));
95
+
96
+ this.socket.on("onMessage", (data) => {
97
+ if (data.isYou === 0) {
98
+ this.emit("message", data.message);
99
+ } else {
100
+ }
101
+ });
102
+
103
+ this.socket.on("onChatEnd", (data) => {
104
+ this.isChatting = false;
105
+ this.partner = null;
106
+ this.emit("chatEnd", data);
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Search for a new chat partner.
112
+ * @param {string} gender 'man' or 'woman'
113
+ * @param {string} partnerGender 'man', 'woman', or 'whatever'
114
+ * @param {string|number} age '1'(<20), '2'(20-24), '3'(>24)
115
+ * @returns {Promise<PartnerData>} Resolves when a partner is found
116
+ */
117
+ async search(gender = "man", partnerGender = "woman", age = "1") {
118
+ if (!this.isConnected) {
119
+ await this.connect();
120
+ }
121
+
122
+ if (this.isChatting) {
123
+ this.endChat();
124
+ }
125
+
126
+ return new Promise((resolve, reject) => {
127
+ this._searchResolver = resolve;
128
+ this._searchRejecter = reject;
129
+
130
+ this.socket.emit("initChat", {
131
+ gender: gender,
132
+ partner_gender: partnerGender,
133
+ ages: String(age)
134
+ });
135
+ });
136
+ }
137
+
138
+ /**
139
+ * Send a text message to the current partner.
140
+ * @param {string} text
141
+ */
142
+ send(text) {
143
+ if (!this.isChatting) {
144
+ console.warn("⚠️ Cannot send message: Not currently in a chat.");
145
+ return;
146
+ }
147
+ this.socket.emit("sendMessage", { message: text });
148
+ }
149
+
150
+ /**
151
+ * Send typing status to partner
152
+ */
153
+ setTyping() {
154
+ if (this.isChatting) {
155
+ this.socket.emit("typing", {});
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Manually end the current chat.
161
+ */
162
+ endChat() {
163
+ if (this.socket && this.isChatting) {
164
+ this.socket.emit("lepis", "manual");
165
+ this.isChatting = false;
166
+ this.partner = null;
167
+ this.emit("chatEnd", { reason: "local" });
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Close socket connection completely.
173
+ */
174
+ close() {
175
+ if (this.socket) {
176
+ this.socket.disconnect();
177
+ this.socket = null;
178
+ this.isConnected = false;
179
+ }
180
+ }
181
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "anotalkjs",
3
+ "version": "1.0.0",
4
+ "description": "A JavaScript client for the Anotalk anonymous chat service.",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "anotalk",
12
+ "chat",
13
+ "anonymous",
14
+ "websocket",
15
+ "socket.io",
16
+ "javascript"
17
+ ],
18
+ "author": "Your Name",
19
+ "license": "ISC",
20
+ "dependencies": {
21
+ "socket.io-client": "^2.3.1"
22
+ }
23
+ }