diff --git a/comty.js b/comty.js
new file mode 160000
index 00000000..8acb3f00
--- /dev/null
+++ b/comty.js
@@ -0,0 +1 @@
+Subproject commit 8acb3f008477bbb782eca1c7f747b494a293e57b
diff --git a/linebridge b/linebridge
index c011f235..6d553830 160000
--- a/linebridge
+++ b/linebridge
@@ -1 +1 @@
-Subproject commit c011f2353f8db14a2ed287015d108c2620098a84
+Subproject commit 6d553830ab4661ffab952253d77ccb0bfc1363d8
diff --git a/packages/app/.config.js b/packages/app/.config.js
index 9b7eaa89..42e16caf 100755
--- a/packages/app/.config.js
+++ b/packages/app/.config.js
@@ -18,7 +18,7 @@ const aliases = {
layouts: path.join(__dirname, "src/layouts"),
hooks: path.join(__dirname, "src/hooks"),
classes: path.join(__dirname, "src/classes"),
- "comty.js": path.join(__dirname, "../", "comty.js", "src"),
+ "comty.js": path.join(__dirname, "../../", "comty.js", "src"),
models: path.join(__dirname, "../comty.js/src/models"),
}
diff --git a/packages/app/constants/routes.js b/packages/app/constants/routes.js
index 1ddcc27d..615fc273 100755
--- a/packages/app/constants/routes.js
+++ b/packages/app/constants/routes.js
@@ -77,6 +77,11 @@ export default [
useLayout: "default",
public: true
},
+ {
+ path: "/apr/*",
+ useLayout: "minimal",
+ public: true
+ },
// THIS MUST BE THE LAST ROUTE
{
path: "/",
diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx
index 8ac2ab0c..473b8fc8 100755
--- a/packages/app/src/App.jsx
+++ b/packages/app/src/App.jsx
@@ -143,9 +143,7 @@ class ComtyApp extends React.Component {
document.getElementById("root").classList.add("electron")
}
- console.log(import.meta.env)
-
- if (import.meta.env.VITE_SENTRY_DSN) {
+ if (import.meta.env.VITE_SENTRY_DSN && import.meta.env.PROD) {
console.log(`Initializing Sentry...`)
Sentry.init({
diff --git a/packages/app/src/components/FollowersList/index.jsx b/packages/app/src/components/FollowersList/index.jsx
index 0694be93..7cbccf5e 100755
--- a/packages/app/src/components/FollowersList/index.jsx
+++ b/packages/app/src/components/FollowersList/index.jsx
@@ -47,7 +47,7 @@ export default (props) => {
console.log(`Loading Followers for [${props.user_id}]...`)
- const followers = await FollowsModel.getFollowers(props.user_id).catch((err) => {
+ const followers = await FollowsModel.getFollowers(props.user_id, true).catch((err) => {
console.error(err)
app.message.error("Failed to fetch followers")
diff --git a/packages/app/src/components/Login/index.jsx b/packages/app/src/components/Login/index.jsx
index 79e4803a..31c26856 100755
--- a/packages/app/src/components/Login/index.jsx
+++ b/packages/app/src/components/Login/index.jsx
@@ -40,30 +40,45 @@ export default class Login extends React.Component {
loginInputs: {},
error: null,
phase: 0,
+ mfa_required: null
}
formRef = React.createRef()
handleFinish = async () => {
+ this.setState({
+ mfa_required: false,
+ })
+
const payload = {
username: this.state.loginInputs.username,
password: this.state.loginInputs.password,
+ mfa_code: this.state.loginInputs.mfa_code,
}
this.clearError()
this.toggleLoading(true)
- await AuthModel.login(payload, () => this.onDone()).catch((error) => {
+ await AuthModel.login(payload, this.onDone).catch((error) => {
console.error(error, error.response)
this.toggleLoading(false)
- this.onError(error.response.data.message)
+ this.onError(error.response.data.error)
return false
})
}
- onDone = async () => {
+ onDone = async ({ mfa_required } = {}) => {
+ if (mfa_required) {
+ this.setState({
+ loading: false,
+ mfa_required: mfa_required,
+ })
+
+ return false
+ }
+
if (typeof this.props.close === "function") {
await this.props.close({
unlock: true
@@ -77,6 +92,18 @@ export default class Login extends React.Component {
return true
}
+ onClickForgotPassword = () => {
+ if (this.props.locked) {
+ this.props.unlock()
+ }
+
+ if (typeof this.props.close === "function") {
+ this.props.close()
+ }
+
+ app.location.push("/apr")
+ }
+
onClickRegister = () => {
if (this.props.locked) {
this.props.unlock()
@@ -238,6 +265,34 @@ export default class Login extends React.Component {
onPressEnter={this.nextStep}
/>
+
+
+ Verification Code
+
+ {
+ this.state.mfa_required && <>
+ We send a verification code to [{this.state.mfa_required.sended_to}]
+
+
+ Didn't receive the code? Resend
+
+ >
+ }
+
+ this.onUpdateInput("mfa_code", e.target.value)}
+ onPressEnter={this.nextStep}
+ />
+
@@ -262,6 +317,10 @@ export default class Login extends React.Component {
{this.state.error}
+
+
diff --git a/packages/app/src/cores/api/api.core.js b/packages/app/src/cores/api/api.core.js
index f81f2c4b..9e003fe3 100755
--- a/packages/app/src/cores/api/api.core.js
+++ b/packages/app/src/cores/api/api.core.js
@@ -29,48 +29,60 @@ export default class APICore extends Core {
}
listenEvent(key, handler, instance) {
- this.instance.wsInstances[instance ?? "default"].on(key, handler)
+ if (!this.instance.wsInstances[instance ?? "default"]) {
+ console.error(`[API] Websocket instance ${instance} not found`)
+
+ return false
+ }
+
+ return this.instance.wsInstances[instance ?? "default"].on(key, handler)
}
unlistenEvent(key, handler, instance) {
- this.instance.wsInstances[instance ?? "default"].off(key, handler)
+ if (!this.instance.wsInstances[instance ?? "default"]) {
+ console.error(`[API] Websocket instance ${instance} not found`)
+
+ return false
+ }
+
+ return this.instance.wsInstances[instance ?? "default"].off(key, handler)
}
pendingPingsFromInstance = {}
createPingIntervals() {
- Object.keys(this.instance.wsInstances).forEach((instance) => {
- this.console.debug(`[API] Creating ping interval for ${instance}`)
+ // Object.keys(this.instance.wsInstances).forEach((instance) => {
+ // this.console.debug(`[API] Creating ping interval for ${instance}`)
- if (this.instance.wsInstances[instance].pingInterval) {
- clearInterval(this.instance.wsInstances[instance].pingInterval)
- }
+ // if (this.instance.wsInstances[instance].pingInterval) {
+ // clearInterval(this.instance.wsInstances[instance].pingInterval)
+ // }
- this.instance.wsInstances[instance].pingInterval = setInterval(() => {
- if (this.instance.wsInstances[instance].pendingPingTry && this.instance.wsInstances[instance].pendingPingTry > 3) {
- this.console.debug(`[API] Ping timeout for ${instance}`)
+ // this.instance.wsInstances[instance].pingInterval = setInterval(() => {
+ // if (this.instance.wsInstances[instance].pendingPingTry && this.instance.wsInstances[instance].pendingPingTry > 3) {
+ // this.console.debug(`[API] Ping timeout for ${instance}`)
- return clearInterval(this.instance.wsInstances[instance].pingInterval)
- }
+ // return clearInterval(this.instance.wsInstances[instance].pingInterval)
+ // }
- const timeStart = Date.now()
+ // const timeStart = Date.now()
- //this.console.debug(`[API] Ping ${instance}`, this.instance.wsInstances[instance].pendingPingTry)
+ // //this.console.debug(`[API] Ping ${instance}`, this.instance.wsInstances[instance].pendingPingTry)
- this.instance.wsInstances[instance].emit("ping", () => {
- this.instance.wsInstances[instance].latency = Date.now() - timeStart
+ // this.instance.wsInstances[instance].emit("ping", () => {
+ // this.instance.wsInstances[instance].latency = Date.now() - timeStart
- this.instance.wsInstances[instance].pendingPingTry = 0
- })
+ // this.instance.wsInstances[instance].pendingPingTry = 0
+ // })
- this.instance.wsInstances[instance].pendingPingTry = this.instance.wsInstances[instance].pendingPingTry ? this.instance.wsInstances[instance].pendingPingTry + 1 : 1
- }, 5000)
+ // this.instance.wsInstances[instance].pendingPingTry = this.instance.wsInstances[instance].pendingPingTry ? this.instance.wsInstances[instance].pendingPingTry + 1 : 1
+ // }, 5000)
- // clear interval on close
- this.instance.wsInstances[instance].on("close", () => {
- clearInterval(this.instance.wsInstances[instance].pingInterval)
- })
- })
+ // // clear interval on close
+ // this.instance.wsInstances[instance].on("close", () => {
+ // clearInterval(this.instance.wsInstances[instance].pingInterval)
+ // })
+ // })
}
async onInitialize() {
@@ -92,8 +104,8 @@ export default class APICore extends Core {
// make a basic request to check if the API is available
await this.instance.instances["default"]({
- method: "GET",
- url: "/ping",
+ method: "head",
+ url: "/",
}).catch((error) => {
this.console.error("[API] Ping error", error)
@@ -105,7 +117,7 @@ export default class APICore extends Core {
this.console.debug("[API] Attached to", this.instance)
- this.createPingIntervals()
+ //this.createPingIntervals()
return this.instance
}
diff --git a/packages/app/src/pages/account/index.jsx b/packages/app/src/pages/account/index.jsx
index d9195337..b7646c67 100755
--- a/packages/app/src/pages/account/index.jsx
+++ b/packages/app/src/pages/account/index.jsx
@@ -56,10 +56,10 @@ export default class Account extends React.Component {
requestedUser: null,
user: null,
- followers: [],
-
isSelf: false,
- isFollowed: false,
+
+ followersCount: 0,
+ following: false,
tabActiveKey: "posts",
@@ -87,8 +87,7 @@ export default class Account extends React.Component {
let isSelf = false
let user = null
- let isFollowed = false
- let followers = []
+ let followersCount = 0
if (requestedUser != null) {
if (token.username === requestedUser) {
@@ -113,33 +112,24 @@ export default class Account extends React.Component {
console.log(`Loaded User [${user.username}] >`, user)
- if (!isSelf) {
- const followedResult = await FollowsModel.imFollowing(user._id).catch(() => false)
-
- if (followedResult) {
- isFollowed = followedResult.isFollowed
- }
- }
-
const followersResult = await FollowsModel.getFollowers(user._id).catch(() => false)
if (followersResult) {
- followers = followersResult
+ followersCount = followersResult.count
}
}
await this.setState({
isSelf,
- user,
requestedUser,
- isFollowed,
- followers,
+ user,
+
+ following: user.following,
+ followersCount: followersCount,
})
}
onPostListTopVisibility = (to) => {
- console.log("onPostListTopVisibility", to)
-
if (to) {
this.profileRef.current.classList.remove("topHidden")
} else {
@@ -149,7 +139,7 @@ export default class Account extends React.Component {
onClickFollow = async () => {
const result = await FollowsModel.toggleFollow({
- username: this.state.requestedUser,
+ user_id: this.state.user._id,
}).catch((error) => {
console.error(error)
antd.message.error(error.message)
@@ -158,8 +148,8 @@ export default class Account extends React.Component {
})
await this.setState({
- isFollowed: result.following,
- followers: result.followers,
+ following: result.following,
+ followersCount: result.count,
})
}
@@ -240,9 +230,9 @@ export default class Account extends React.Component {
ref={this.actionsRef}
>
diff --git a/packages/app/src/pages/apr/index.jsx b/packages/app/src/pages/apr/index.jsx
new file mode 100644
index 00000000..a4b2e967
--- /dev/null
+++ b/packages/app/src/pages/apr/index.jsx
@@ -0,0 +1,11 @@
+import React from "react"
+
+import "./index.less"
+
+const AccountPasswordRecovery = () => {
+ return
+
Account Password Recovery
+
+}
+
+export default AccountPasswordRecovery
\ No newline at end of file
diff --git a/packages/app/src/pages/apr/index.less b/packages/app/src/pages/apr/index.less
new file mode 100644
index 00000000..d850d946
--- /dev/null
+++ b/packages/app/src/pages/apr/index.less
@@ -0,0 +1,3 @@
+.password_recover {
+ padding: 20px;
+}
\ No newline at end of file
diff --git a/packages/app/src/pages/auth/index.less b/packages/app/src/pages/auth/index.less
index ff0ddcfa..326303dc 100755
--- a/packages/app/src/pages/auth/index.less
+++ b/packages/app/src/pages/auth/index.less
@@ -46,6 +46,7 @@
flex-direction: row;
width: 55vw;
+ min-width: 700px;
max-width: 800px;
overflow: hidden;
@@ -83,6 +84,8 @@
width: 100%;
+ min-width: 420px;
+
padding: 40px;
.content_header {
diff --git a/packages/comty.js/package.json b/packages/comty.js/package.json
deleted file mode 100755
index 35093759..00000000
--- a/packages/comty.js/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "comty.js",
- "version": "0.60.3",
- "main": "./dist/index.js",
- "author": "RageStudio ",
- "scripts": {
- "build": "hermes build"
- },
- "files": [
- "dist"
- ],
- "license": "MIT",
- "dependencies": {
- "@foxify/events": "^2.1.0",
- "axios": "^1.4.0",
- "js-cookie": "^3.0.5",
- "jsonwebtoken": "^9.0.0",
- "jwt-decode": "^3.1.2",
- "luxon": "^3.3.0",
- "socket.io-client": "^4.6.1"
- },
- "devDependencies": {
- "@ragestudio/hermes": "^0.1.0",
- "corenode": "^0.28.26"
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/handlers/measurePing.js b/packages/comty.js/src/handlers/measurePing.js
deleted file mode 100755
index 20a3774c..00000000
--- a/packages/comty.js/src/handlers/measurePing.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import request from "./request"
-
-export default async () => {
- const timings = {}
-
- const promises = [
- new Promise(async (resolve) => {
- const start = Date.now()
-
- const failTimeout = setTimeout(() => {
- timings.http = "failed"
-
- resolve()
- }, 10000)
-
- request({
- method: "GET",
- url: "/ping",
- })
- .then(() => {
- // set http timing in ms
- timings.http = Date.now() - start
-
- failTimeout && clearTimeout(failTimeout)
-
- resolve()
- })
- .catch(() => {
- timings.http = "failed"
-
- resolve()
- })
- }),
- new Promise((resolve) => {
- const start = Date.now()
-
- const failTimeout = setTimeout(() => {
- timings.ws = "failed"
-
- resolve()
- }, 10000)
-
- __comty_shared_state.wsInstances["default"].on("pong", () => {
- timings.ws = Date.now() - start
-
- failTimeout && clearTimeout(failTimeout)
-
- resolve()
- })
-
- __comty_shared_state.wsInstances["default"].emit("ping")
- })
- ]
-
- await Promise.all(promises)
-
- return timings
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/handlers/request.js b/packages/comty.js/src/handlers/request.js
deleted file mode 100755
index 852e0539..00000000
--- a/packages/comty.js/src/handlers/request.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import handleBeforeRequest from "../helpers/handleBeforeRequest"
-import handleAfterRequest from "../helpers/handleAfterRequest"
-
-export default async (
- request = {
- method: "GET",
- },
- ...args
-) => {
- const instance = request.instance ?? __comty_shared_state.instances.default
-
- if (!instance) {
- throw new Error("No instance provided")
- }
-
- // handle before request
- await handleBeforeRequest(request)
-
- if (typeof request === "string") {
- request = {
- url: request,
- }
- }
-
- if (typeof request.headers !== "object") {
- request.headers = {}
- }
-
- let result = null
-
- const makeRequest = async () => {
- const _result = await instance(request, ...args)
- .catch((error) => {
- return error
- })
-
- result = _result
- }
-
- await makeRequest()
-
- // handle after request
- await handleAfterRequest(result, makeRequest)
-
- // if error, throw it
- if (result instanceof Error) {
- throw result
- }
-
- return result
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/helpers/handleAfterRequest.js b/packages/comty.js/src/helpers/handleAfterRequest.js
deleted file mode 100755
index 3840d158..00000000
--- a/packages/comty.js/src/helpers/handleAfterRequest.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import handleRegenerationEvent from "./handleRegenerationEvent"
-
-export default async (data, callback) => {
- // handle 401, 403 responses
- if (data instanceof Error) {
- if (data.code && (data.code === "ECONNABORTED" || data.code === "ERR_NETWORK")) {
- console.error(`Request aborted or network error, ignoring`)
- return false
- }
-
- if (data.response.status === 401) {
- // check if the server issue a refresh token on data
- if (data.response.data.refreshToken) {
- console.log(`Session expired, but the server issued a refresh token, handling regeneration event`)
-
- // handle regeneration event
- await handleRegenerationEvent(data.response.data.refreshToken)
-
- return await callback()
- }
-
- // check if route is from "session" namespace
- if (data.config.url.includes("/session")) {
- return __comty_shared_state.eventBus.emit("session.invalid", "Session expired, but the server did not issue a refresh token")
- }
- }
-
- if (data.response.status === 403) {
- if (data.config.url.includes("/session")) {
- return __comty_shared_state.eventBus.emit("session.invalid", "Session not valid or not existent")
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/helpers/handleBeforeRequest.js b/packages/comty.js/src/helpers/handleBeforeRequest.js
deleted file mode 100755
index be7cbee3..00000000
--- a/packages/comty.js/src/helpers/handleBeforeRequest.js
+++ /dev/null
@@ -1,13 +0,0 @@
-export default async (request) => {
- if (__comty_shared_state.onExpiredExceptionEvent) {
- if (__comty_shared_state.excludedExpiredExceptionURL.includes(request.url)) return
-
- await new Promise((resolve) => {
- __comty_shared_state.eventBus.once("session.regenerated", () => {
- console.log(`Session has been regenerated, retrying request`)
-
- resolve()
- })
- })
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/helpers/handleRegenerationEvent.js b/packages/comty.js/src/helpers/handleRegenerationEvent.js
deleted file mode 100755
index 9f67575c..00000000
--- a/packages/comty.js/src/helpers/handleRegenerationEvent.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import SessionModel from "../models/session"
-import request from "../handlers/request"
-import { reconnectWebsockets } from "../"
-
-export default async (refreshToken) => {
- __comty_shared_state.eventBus.emit("session.expiredExceptionEvent", refreshToken)
-
- __comty_shared_state.onExpiredExceptionEvent = true
-
- const expiredToken = await SessionModel.token
-
- // send request to regenerate token
- const response = await request({
- method: "POST",
- url: "/session/regenerate",
- data: {
- expiredToken: expiredToken,
- refreshToken,
- }
- }).catch((error) => {
- console.error(`Failed to regenerate token: ${error.message}`)
- return false
- })
-
- if (!response) {
- return __comty_shared_state.eventBus.emit("session.invalid", "Failed to regenerate token")
- }
-
- if (!response.data?.token) {
- return __comty_shared_state.eventBus.emit("session.invalid", "Failed to regenerate token, invalid server response.")
- }
-
- // set new token
- SessionModel.token = response.data.token
-
- __comty_shared_state.onExpiredExceptionEvent = false
-
- // emit event
- __comty_shared_state.eventBus.emit("session.regenerated")
-
- // reconnect websockets
- reconnectWebsockets()
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/helpers/withSettings.js b/packages/comty.js/src/helpers/withSettings.js
deleted file mode 100755
index d48e243b..00000000
--- a/packages/comty.js/src/helpers/withSettings.js
+++ /dev/null
@@ -1,25 +0,0 @@
-export default class Settings {
- static get = (key) => {
- if (typeof window === "undefined") {
- return null
- }
-
- return window?.app?.cores?.settings.get(key)
- }
-
- static set = (key, value) => {
- if (typeof window === "undefined") {
- return null
- }
-
- return window?.app?.cores?.settings.set(key, value)
- }
-
- static is = (key) => {
- if (typeof window === "undefined") {
- return null
- }
-
- return window?.app?.cores?.settings.is(key)
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/helpers/withStorage.js b/packages/comty.js/src/helpers/withStorage.js
deleted file mode 100755
index bbea9678..00000000
--- a/packages/comty.js/src/helpers/withStorage.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import jscookies from "js-cookie"
-
-class InternalStorage {
- #storage = {}
-
- get(key) {
- // get value from storage
- return this.#storage[key]
- }
-
- set(key, value) {
- // storage securely in memory
- return this.#storage[key] = value
- }
-}
-
-export default class Storage {
- static get engine() {
- // check if is running in browser, if is import js-cookie
- // else use in-memory safe storage
- if (typeof window !== "undefined") {
- return jscookies
- }
-
- if (!globalThis.__comty_shared_state["_internal_storage"]) {
- globalThis.__comty_shared_state["_internal_storage"] = new InternalStorage()
- }
-
- return globalThis.__comty_shared_state["_internal_storage"]
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/hooks/useRequest/index.js b/packages/comty.js/src/hooks/useRequest/index.js
deleted file mode 100755
index 0dd2b7a6..00000000
--- a/packages/comty.js/src/hooks/useRequest/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from "react"
-
-export default (method, ...args) => {
- if (typeof method !== "function") {
- throw new Error("useRequest: method must be a function")
- }
-
- const [loading, setLoading] = React.useState(true)
- const [result, setResult] = React.useState(null)
- const [error, setError] = React.useState(null)
-
- const makeRequest = (...newArgs) => {
- method(...newArgs)
- .then((data) => {
- setResult(data)
- setLoading(false)
- })
- .catch((err) => {
- setError(err)
- setLoading(false)
- })
- }
-
- React.useEffect(() => {
- makeRequest(...args)
- }, [])
-
- return [loading, result, error, (...newArgs) => {
- setLoading(true)
- makeRequest(...newArgs)
- }]
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/index.js b/packages/comty.js/src/index.js
deleted file mode 100755
index 9b64c944..00000000
--- a/packages/comty.js/src/index.js
+++ /dev/null
@@ -1,201 +0,0 @@
-import pkg from "../package.json"
-import EventEmitter from "@foxify/events"
-
-import axios from "axios"
-import { io } from "socket.io-client"
-
-import remotes from "./remotes"
-
-//import request from "./handlers/request"
-import Storage from "./helpers/withStorage"
-
-import SessionModel from "./models/session"
-import { createHandlers } from "./models"
-
-globalThis.isServerMode = typeof window === "undefined" && typeof global !== "undefined"
-
-if (globalThis.isServerMode) {
- const { Buffer } = require("buffer")
-
- globalThis.b64Decode = (data) => {
- return Buffer.from(data, "base64").toString("utf-8")
- }
- globalThis.b64Encode = (data) => {
- return Buffer.from(data, "utf-8").toString("base64")
- }
-}
-
-export async function createWebsockets() {
- const instances = globalThis.__comty_shared_state.wsInstances
-
- for (let [key, instance] of Object.entries(instances)) {
- if (instance.connected) {
- // disconnect first
- instance.disconnect()
- }
-
- // remove current listeners
- instance.removeAllListeners()
-
- delete globalThis.__comty_shared_state.wsInstances[key]
- }
-
- for (let [key, remote] of Object.entries(remotes)) {
- if (!remote.hasWebsocket) {
- continue
- }
-
- let opts = {
- transports: ["websocket"],
- autoConnect: remote.autoConnect ?? true,
- ...remote.wsParams ?? {},
- }
-
- if (remote.noAuth !== true) {
- opts.auth = {
- token: SessionModel.token,
- }
- }
-
- globalThis.__comty_shared_state.wsInstances[key] = io(remote.wsOrigin ?? remote.origin, opts)
- }
-
- // regsister events
- for (let [key, instance] of Object.entries(instances)) {
- instance.on("connect", () => {
- console.debug(`[WS-API][${key}] Connected`)
-
- if (remotes[key].useClassicAuth && remotes[key].noAuth !== true) {
- // try to auth
- instance.emit("auth", {
- token: SessionModel.token,
- })
- }
-
- globalThis.__comty_shared_state.eventBus.emit(`${key}:connected`)
- })
-
- instance.on("disconnect", () => {
- console.debug(`[WS-API][${key}] Disconnected`)
-
- globalThis.__comty_shared_state.eventBus.emit(`${key}:disconnected`)
- })
-
- instance.on("error", (error) => {
- console.error(`[WS-API][${key}] Error`, error)
-
- globalThis.__comty_shared_state.eventBus.emit(`${key}:error`, error)
- })
-
- instance.onAny((event, ...args) => {
- console.debug(`[WS-API][${key}] Event (${event})`, ...args)
-
- globalThis.__comty_shared_state.eventBus.emit(`${key}:${event}`, ...args)
- })
- }
-}
-
-export async function disconnectWebsockets() {
- const instances = globalThis.__comty_shared_state.wsInstances
-
- for (let [key, instance] of Object.entries(instances)) {
- if (instance.connected) {
- instance.disconnect()
- }
- }
-}
-
-export async function reconnectWebsockets({ force = false } = {}) {
- const instances = globalThis.__comty_shared_state.wsInstances
-
- for (let [key, instance] of Object.entries(instances)) {
- if (instance.connected) {
- if (!instance.auth) {
- instance.disconnect()
-
- instance.auth = {
- token: SessionModel.token,
- }
-
- instance.connect()
- continue
- }
-
- if (!force) {
- instance.emit("reauthenticate", {
- token: SessionModel.token,
- })
-
- continue
- }
-
- // disconnect first
- instance.disconnect()
- }
-
- if (remotes[key].noAuth !== true) {
- instance.auth = {
- token: SessionModel.token,
- }
- }
-
- instance.connect()
- }
-}
-
-export default function createClient({
- accessKey = null,
- privateKey = null,
- enableWs = false,
-} = {}) {
- const sharedState = globalThis.__comty_shared_state = {
- onExpiredExceptionEvent: false,
- excludedExpiredExceptionURL: ["/session/regenerate"],
- eventBus: new EventEmitter(),
- mainOrigin: remotes.default.origin,
- instances: Object(),
- wsInstances: Object(),
- rest: null,
- version: pkg.version,
- }
-
- if (globalThis.isServerMode) {
- sharedState.rest = createHandlers()
- }
-
- if (privateKey && accessKey && globalThis.isServerMode) {
- Storage.engine.set("token", `${accessKey}:${privateKey}`)
- }
-
- // create instances for every remote
- for (const [key, remote] of Object.entries(remotes)) {
- sharedState.instances[key] = axios.create({
- baseURL: remote.origin,
- headers: {
- "Content-Type": "application/json",
- }
- })
-
- // create a interceptor to attach the token every request
- sharedState.instances[key].interceptors.request.use((config) => {
- // check if current request has no Authorization header, if so, attach the token
- if (!config.headers["Authorization"]) {
- const sessionToken = SessionModel.token
-
- if (sessionToken) {
- config.headers["Authorization"] = `${globalThis.isServerMode ? "Server" : "Bearer"} ${sessionToken}`
- } else {
- console.warn("Making a request with no session token")
- }
- }
-
- return config
- })
- }
-
- if (enableWs) {
- createWebsockets()
- }
-
- return sharedState
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/models/auth/index.js b/packages/comty.js/src/models/auth/index.js
deleted file mode 100755
index 20490419..00000000
--- a/packages/comty.js/src/models/auth/index.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import request from "../../handlers/request"
-import SessionModel from "../session"
-
-const emailRegex = new RegExp(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/)
-
-export default class AuthModel {
- static login = async (payload, callback) => {
- const response = await request({
- method: "post",
- url: "/auth/login",
- data: {
- username: payload.username, //window.btoa(payload.username),
- password: payload.password, //window.btoa(payload.password),
- },
- })
-
- SessionModel.token = response.data.token
-
- if (typeof callback === "function") {
- await callback()
- }
-
- __comty_shared_state.eventBus.emit("auth:login_success")
-
- return response.data
- }
-
- static logout = async () => {
- await SessionModel.destroyCurrentSession()
-
- SessionModel.removeToken()
-
- __comty_shared_state.eventBus.emit("auth:logout_success")
- }
-
- static register = async (payload) => {
- const { username, password, email } = payload
-
- const response = await request({
- method: "post",
- url: "/auth/register",
- data: {
- username,
- password,
- email,
- }
- }).catch((error) => {
- console.error(error)
-
- return false
- })
-
- if (!response) {
- throw new Error("Unable to register user")
- }
-
- return response
- }
-
- static usernameValidation = async (username) => {
- let payload = {}
-
- // check if usename arguemnt is an email
- if (emailRegex.test(username)) {
- payload.email = username
- } else {
- payload.username = username
- }
-
- const response = await request({
- method: "get",
- url: "/auth/login/validation",
- params: payload,
- }).catch((error) => {
- console.error(error)
-
- return false
- })
-
- if (!response) {
- throw new Error("Unable to validate user")
- }
-
- return response.data
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/models/feed/index.js b/packages/comty.js/src/models/feed/index.js
deleted file mode 100755
index fef3ba08..00000000
--- a/packages/comty.js/src/models/feed/index.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import request from "../../handlers/request"
-import Settings from "../../helpers/withSettings"
-
-export default class FeedModel {
- static getMusicFeed = async ({ trim, limit } = {}) => {
- const { data } = await request({
- method: "GET",
- url: `/feed/music`,
- params: {
- trim: trim ?? 0,
- limit: limit ?? Settings.get("feed_max_fetch"),
- }
- })
-
- return data
- }
-
- static getGlobalMusicFeed = async ({ trim, limit } = {}) => {
- const { data } = await request({
- method: "GET",
- url: `/feed/music/global`,
- params: {
- trim: trim ?? 0,
- limit: limit ?? Settings.get("feed_max_fetch"),
- }
- })
-
- return data
- }
-
- static getTimelineFeed = async ({ trim, limit = 10 } = {}) => {
- const { data } = await request({
- method: "GET",
- url: `/feed/timeline`,
- params: {
- trim: trim ?? 0,
- limit: limit ?? Settings.get("feed_max_fetch"),
- }
- })
-
- return data
- }
-
- static getPostsFeed = async ({ trim, limit } = {}) => {
- const { data } = await request({
- method: "GET",
- url: `/feed/posts`,
- params: {
- trim: trim ?? 0,
- limit: limit ?? Settings.get("feed_max_fetch"),
- }
- })
-
- return data
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/models/follows/index.js b/packages/comty.js/src/models/follows/index.js
deleted file mode 100755
index 56986a79..00000000
--- a/packages/comty.js/src/models/follows/index.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { SessionModel } from "../../models"
-import request from "../../handlers/request"
-
-export default class FollowsModel {
- static imFollowing = async (user_id) => {
- if (!user_id) {
- throw new Error("user_id is required")
- }
-
- const response = await request({
- method: "GET",
- url: `/follow/user/${user_id}`,
- })
-
- return response.data
- }
-
- static getFollowers = async (user_id) => {
- if (!user_id) {
- // set current user_id
- user_id = SessionModel.user_id
- }
-
- const response = await request({
- method: "GET",
- url: `/follow/user/${user_id}/followers`,
- })
-
- return response.data
- }
-
- static toggleFollow = async ({ user_id, username }) => {
- if (!user_id && !username) {
- throw new Error("user_id or username is required")
- }
-
- const response = await request({
- method: "POST",
- url: "/follow/user/toggle",
- data: {
- user_id: user_id,
- username: username
- },
- })
-
- return response.data
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/models/index.js b/packages/comty.js/src/models/index.js
deleted file mode 100755
index 11d514c3..00000000
--- a/packages/comty.js/src/models/index.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import AuthModel from "./auth"
-import FeedModel from "./feed"
-import FollowsModel from "./follows"
-import LivestreamModel from "./livestream"
-import PostModel from "./post"
-import SessionModel from "./session"
-import SyncModel from "./sync"
-import UserModel from "./user"
-
-function getEndpointsFromModel(model) {
- return Object.entries(model).reduce((acc, [key, value]) => {
- acc[key] = value
-
- return acc
- }, {})
-}
-
-function createHandlers() {
- return {
- auth: getEndpointsFromModel(AuthModel),
- feed: getEndpointsFromModel(FeedModel),
- follows: getEndpointsFromModel(FollowsModel),
- livestream: getEndpointsFromModel(LivestreamModel),
- post: getEndpointsFromModel(PostModel),
- session: getEndpointsFromModel(SessionModel),
- sync: getEndpointsFromModel(SyncModel),
- user: getEndpointsFromModel(UserModel),
- }
-}
-
-export {
- AuthModel,
- FeedModel,
- FollowsModel,
- LivestreamModel,
- PostModel,
- SessionModel,
- SyncModel,
- UserModel,
- createHandlers,
-}
diff --git a/packages/comty.js/src/models/livestream/index.js b/packages/comty.js/src/models/livestream/index.js
deleted file mode 100755
index 5393b23e..00000000
--- a/packages/comty.js/src/models/livestream/index.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import request from "../../handlers/request"
-
-export default class Livestream {
- static deleteProfile = async (profile_id) => {
- const response = await request({
- method: "DELETE",
- url: `/tv/streaming/profile`,
- data: {
- profile_id
- }
- })
-
- return response.data
- }
-
- static postProfile = async (payload) => {
- const response = await request({
- method: "POST",
- url: `/tv/streaming/profile`,
- data: payload,
- })
-
- return response.data
- }
-
- static getProfiles = async () => {
- const response = await request({
- method: "GET",
- url: `/tv/streaming/profiles`,
- })
-
- return response.data
- }
-
- static regenerateStreamingKey = async (profile_id) => {
- const response = await request({
- method: "POST",
- url: `/tv/streaming/regenerate_key`,
- data: {
- profile_id
- }
- })
-
- return response.data
- }
-
- static getCategories = async (key) => {
- const response = await request({
- method: "GET",
- url: `/tv/streaming/categories`,
- params: {
- key,
- }
- })
-
- return response.data
- }
-
- static getLivestream = async (payload = {}) => {
- if (!payload.username) {
- throw new Error("Username is required")
- }
-
- let response = await request({
- method: "GET",
- url: `/tv/streams`,
- params: {
- username: payload.username,
- profile_id: payload.profile_id,
- }
- })
-
- return response.data
- }
-
- static getLivestreams = async () => {
- const response = await request({
- method: "GET",
- url: `/tv/streams`,
- })
-
- return response.data
- }
-}
\ No newline at end of file
diff --git a/packages/comty.js/src/models/music/index.js b/packages/comty.js/src/models/music/index.js
deleted file mode 100755
index bff3c5cb..00000000
--- a/packages/comty.js/src/models/music/index.js
+++ /dev/null
@@ -1,561 +0,0 @@
-import request from "../../handlers/request"
-import pmap from "p-map"
-import SyncModel from "../sync"
-
-export default class MusicModel {
- static get api_instance() {
- return globalThis.__comty_shared_state.instances["music"]
- }
-
- /**
- * Retrieves the official featured playlists.
- *
- * @return {Promise