UNPKG

@haelp/teto

Version:

A typescript-based controllable TETR.IO client.

235 lines (234 loc) 8.73 kB
import { Relationship } from "./relationship.mjs"; const processRelationship = (r, selfID)=>({ ...r, user: { id: r.from._id === selfID ? r.to._id : r.from._id, username: r.from._id === selfID ? r.to.username : r.from.username, avatar: r.from._id === selfID ? r.to.avatar_revision : r.from.avatar_revision } }); export class Social { client; /** The current number of people online */ online; /** List of the client's friends */ friends; /** List of "pending" relationships (shows in `other` tab on TETR.IO) */ other; /** people you block */ blocked; /** Notifications */ notifications; /** @hideconstructor */ constructor(client, init){ this.client = client; this.init(); this.online = init.online; this.friends = init.friends.map((r)=>new Relationship({ id: r.user.id, relationshipID: r._id, username: r.user.username, avatar: r.user.avatar }, this, this.client)); this.other = init.other.map((r)=>new Relationship({ id: r.user.id, relationshipID: r._id, username: r.user.username, avatar: r.user.avatar }, this, this.client)); this.blocked = init.blocked; this.notifications = init.notifications; } static async create(client, initData) { const rel = initData.relationships.map((r)=>processRelationship(r, client.user.id)); const data = { online: initData.total_online, notifications: initData.notifications, friends: rel.filter((r)=>r.type === "friend"), other: rel.filter((r)=>r.type === "pending"), blocked: rel.filter((r)=>r.type === "block").map((r)=>({ id: r.user.id, username: r.user.username, avatar: r.user.avatar })) }; return new Social(client, data); } get api() { return this.client.api; } init() { setTimeout(()=>this.notifications.forEach((n)=>{ if (n.type === "friend") { if (!n.seen) { const rel = processRelationship(n.data.relationship, this.client.user.id); this.client.emit("client.friended", { id: rel.user.id, name: rel.user.username, avatar: rel.user.avatar }); } } }), 0); this.client.on("social.online", (count)=>{ this.online = count; }); this.client.on("social.notification", async (n)=>{ this.notifications.splice(0, 0, n); if (n.type === "friend") { const rel = processRelationship(n.data.relationship, this.client.user.id); this.client.emit("client.friended", { id: rel.user.id, name: rel.user.username, avatar: rel.user.avatar }); const user = this.get({ id: rel.user.id }); if (!user) { this.other.push(new Relationship({ id: rel.user.id, username: rel.user.username, avatar: rel.user.avatar, relationshipID: "" }, this, this.client)); } } }); this.client.on("social.dm", async (dm)=>{ let user = this.get({ id: dm.data.user }); if (user) { if (!user.dmsLoaded) await user.loadDms(); else user.dms.push(dm); } else { const u = await this.who(dm.data.user); this.other.push(new Relationship({ id: u._id, username: u.username, avatar: u.avatar_revision, relationshipID: "" }, this, this.client)); user = this.get({ id: dm.data.user }); await user.loadDms(); } this.client.emit("client.dm", { user, content: dm.data.content, reply: async (content)=>{ await this.dm(dm.data.user, content); } }); }); } /** * Marks all notifications as read * @example * client.social.markNotificationsAsRead(); */ markNotificationsAsRead() { this.client.emit("social.notification.ack"); } get(target) { if (typeof target === "string") return this.friends.find((r)=>r.id === target || r.username === target) || this.other.find((r)=>r.id === target || r.username === target) || null; else if ("id" in target) return this.friends.find((r)=>r.id === target.id) || this.other.find((r)=>r.id === target.id) || null; else return this.friends.find((r)=>r.username === target.username) || this.other.find((r)=>r.username === target.username) || null; } /** * Get the user id given a username */ async resolve(username) { return await this.api.users.resolve(username); } async who(id) { return this.api.users.get({ id }); } /** * Send a message to a specified user (based on id) * @example * await client.social.dm(await client.social.resolve('halp'), 'what\'s up?'); */ async dm(userID, message) { return await this.client.wrap("social.dm", { recipient: userID, msg: message }, "social.dm", [ "social.dm.fail", "client.error" ]); } /** * Send a user a friend request * @example * await client.social.friend(await client.social.resolve('halp')); * @returns false if the user is already friended, true otherwise * @throws {Error} If an error occurs (such as the user has blocked the client, etc) */ async friend(userID) { if (this.friends.find((r)=>r.id === userID)) return false; await this.api.social.friend(userID); const userData = await this.who(userID); this.friends.push(new Relationship({ id: userData._id, relationshipID: "", username: userData.username, avatar: userData.avatar_revision }, this, this.client)); return true; } /** * Unfriend a user. Note: unfriending a user will unblock them if they are blocked. * @example * await client.social.unfriend(await client.social.resolve('halp')); * @returns false if the user is not unfriended, true otherwise */ async unfriend(userID) { if (!this.friends.find((r)=>r.id === userID)) return false; await this.api.social.unfriend(userID); this.friends = this.friends.filter((r)=>r.id !== userID); return true; } /** * Block a user * @example * await client.social.block(await client.social.resolve('halp')); * @returns false if the user is already blocked, true otherwise */ async block(userID) { if (this.blocked.find((r)=>r.id === userID)) return false; await this.api.social.block(userID); } /** * Unblock a user. Note: unblocking a user will unfriend them if they are friended. * @example * await client.social.unblock(await client.social.resolve('halp')); * @returns false if the user is not unblocked, true otherwise */ async unblock(userID) { await this.api.social.unblock(userID); } /** * Invite a user to your room * @example * await client.social.invite(await client.social.resolve('halp')); */ invite(userID) { return new Promise(async (resolve, reject)=>{ let r = false; this.client.emit("social.invite", userID); const l = (e)=>{ if (r) return; r = true; reject(e); }; this.client.once("client.error", l); await new Promise((r)=>setTimeout(r, 100)); this.client.off("client.error", l); r = true; resolve(); }); } /** * Set the client's status * @example * client.social.status('online', 'lobby:X-QP'); */ status(status, detail = "") { this.client.emit("social.presence", { status, detail }); } } export * from "./relationship.mjs"; //# sourceMappingURL=index.js.map