wnox 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

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.
wnox/__init__.py CHANGED
@@ -5,11 +5,22 @@ import logging
5
5
  from slixmpp import ClientXMPP
6
6
  import ssl
7
7
  import json
8
- from bson import ObjectId # If you need ObjectId validation
8
+ from bson import ObjectId
9
9
  import requests as r
10
10
 
11
+ import random
12
+ import string
13
+
11
14
  nest_asyncio.apply()
15
+ eventdatax = {}
16
+ eventsx = {}
12
17
  # logging.basicConfig(level=logging.DEBUG)
18
+
19
+ def serial_generator(length: int) -> str:
20
+ chars = string.digits + string.ascii_uppercase + string.ascii_lowercase
21
+ random_string = ''.join(random.choice(chars) for _ in range(length))
22
+ return random_string
23
+
13
24
  class EventEmitter:
14
25
  def __init__(self):
15
26
  self._events = {}
@@ -31,43 +42,41 @@ class EventEmitter:
31
42
  results.append(result)
32
43
  return results[0]
33
44
 
34
- class __WebSocketXMPP(ClientXMPP, EventEmitter):
35
- def __init__(self, jid, password):
45
+ class WSX(ClientXMPP, EventEmitter):
46
+ connected = False
47
+ def __init__(self, jid, password, app:str, uid:str, resource:str):
36
48
 
37
-
38
49
  ClientXMPP.__init__(self, jid, password)
39
50
  EventEmitter.__init__(self)
40
- print(f"connecting to {jid} - {password}")
41
- # self.jid = jid
51
+ self.app = app
52
+ self.uid = uid
53
+ self._resource = resource
42
54
  self.password = password
43
- # self.callback = callback # Store the callback function
44
55
  self.add_event_handler("session_start", self.start)
45
56
  self.add_event_handler("failed_auth", self.on_failed_auth)
46
57
  self.add_event_handler("disconnected", self.on_disconnect)
47
- self.add_event_handler("message", self.on_message) # Add event handler for incoming messages
58
+ self.add_event_handler("message", self.on_message)
48
59
 
49
60
  async def start(self, event):
50
61
  """Handle session start."""
51
62
  print("[bridge] connected.")
52
- self.send_presence()
63
+ self.send_presence(ptype="presence")
53
64
  await self.get_roster()
65
+ await self.emit("connect",{})
66
+ self.connected = True
54
67
 
55
- # Send a test message
56
- self.send_message(mto="ethan@qepal.com", mbody="Hello via WebSocket!")
57
- print("[📩] Message sent to ethan@qepal.com")
58
68
 
59
69
  def on_failed_auth(self, event):
60
70
  """Handle authentication failure."""
61
- # print("[❌] Authentication failed. Check username/password.")
62
71
 
63
- def on_disconnect(self, event):
72
+ async def on_disconnect(self, event):
64
73
  """Handle disconnection and attempt reconnection."""
65
- # print("[❌] Disconnected from server. Attempting to reconnect...")
74
+ await self.emit("disconnect",{})
75
+ self.connected = False
66
76
  asyncio.create_task(self.reconnect())
67
77
 
68
78
  async def reconnect(self):
69
- await asyncio.sleep(5) # Wait before reconnecting
70
- print("[🔄] Reconnecting...")
79
+ await asyncio.sleep(5)
71
80
  self.connect(address=("direct.qepal.com", 5222), disable_starttls=False, force_starttls=True)
72
81
  self.process(forever=False)
73
82
 
@@ -78,14 +87,15 @@ class __WebSocketXMPP(ClientXMPP, EventEmitter):
78
87
  from_jid = str(stanza['from'])
79
88
  itsme = from_jid and f"{self.boundjid.bare.split('@')[0]}-{self.boundjid.bare.split('@')[1]}" in from_jid
80
89
  itsbro = not itsme and f"{self.boundjid.bare.split('@')[0]}-" in from_jid
90
+
91
+ if "conference.qepal.com" in from_jid:
92
+ itsme = f"{self.app}-{self.uid}-{self._resource}" in from_jid
93
+ itsbro = not itsme and f"{self.app}-{self.uid}-" in from_jid
94
+
81
95
  delayed = "urn:xmpp:delay" in str(stanza)
82
96
 
83
97
  if body and not delayed:
84
98
  user_uid = from_jid.split('@')[0]
85
- is_app = False
86
- if len(user_uid) != 24 or not ObjectId.is_valid(user_uid):
87
- user_uid = user_uid.split("-")[-1]
88
- is_app = True
89
99
 
90
100
  if body.startswith("{"):
91
101
  try:
@@ -103,43 +113,95 @@ class __WebSocketXMPP(ClientXMPP, EventEmitter):
103
113
  mbody=json.dumps({**result, "mid": json_data.get("mid")})
104
114
  )
105
115
  else:
106
- await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro, "is_app":is_app})
116
+ if "mid" in json_data:
117
+ data = {key: val for key, val in json_data.items() if key != "mid"}
118
+ eventdatax[json_data.get("mid")] = data
119
+ if json_data.get("mid") in eventsx:
120
+ eventsx.get(json_data.get("mid")).set()
121
+ else:
122
+ await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro})
123
+
107
124
  except json.JSONDecodeError:
108
125
  pass
109
126
  else:
110
- await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro, "is_app":is_app})
127
+ await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro})
111
128
 
112
129
 
113
130
 
114
131
  class App:
132
+
115
133
  def __init__(self, *, app:str, resource:str, securekey:str, image:str, public:bool=False):
116
134
  self.app = app
135
+ self.channels = set()
117
136
  self.resource = resource
118
137
  self.securekey = securekey
119
138
  self.image = image
120
139
  self.public = public
121
140
 
122
- json = r.post("https://qepal.com/api/bridge/worker/init", json={
141
+ _json = r.post("https://qepal.com/api/bridge/worker/init", json={
123
142
  "app":app, "resource":resource, "securekey":securekey, "image":image, "public":public}).json()
124
143
 
125
- self.uid = json["uid"]
144
+ self.uid = _json["uid"]
126
145
  self.myjid = self.app + "-" + str(self.uid) + "@qepal.com/" + self.resource
127
- self.password = json["password"]
128
- self.xmpp = __WebSocketXMPP(self.myjid, self.password)
146
+ self.password = _json["password"]
147
+ self.xmpp = WSX(self.myjid, self.password, self.app, self.uid, self.resource)
129
148
 
130
149
  def on(self, api:str, cb:callable):
131
150
  self.xmpp.on(api, cb)
132
151
 
152
+ def sendtojid(self, jid:str, body:str):
153
+ self.xmpp.send_message(mto=jid, mbody=body)
154
+
155
+ def connected(self):
156
+ return self.xmpp.connected
157
+
158
+ async def api(self, app:str, cmd:str, body:dict, jid:str = None, prioritize_public:bool = False):
159
+ if jid == None:
160
+ res:dict = r.post("https://qepal.com/api/bridge/worker/findfreeresource", json={ "app":app, "securekey": self.securekey }).json()
161
+ jids = list(res.get("jids",[]))
162
+ if len(jids) > 0:
163
+ if prioritize_public:
164
+ jid = jids[-1]
165
+ else:
166
+ jid = jids[0]
167
+ if jid == None:
168
+ print("unable to send api (-1)")
169
+ return
170
+
171
+ mid = serial_generator(10)
172
+ msg = {"mid":mid, "api":cmd, **body }
173
+ eventsx[mid] = asyncio.Event()
174
+ self.sendtojid(jid, json.dumps(msg))
175
+ await eventsx[mid].wait()
176
+ data = eventdatax.get(mid)
177
+ return data
178
+
179
+
180
+
181
+ def subscribe(self, channelname:str):
182
+ self.xmpp.send_presence(pto=channelname+ "@conference.qepal.com/"+ self.app + "-" + self.uid + "-" + self.resource , ptype="presence")
183
+ self.xmpp.get_roster()
184
+ self.channels.add(channelname)
185
+
186
+ def unsubscribe(self, channelname:str):
187
+ self.xmpp.send_presence(pto=channelname+ "@conference.qepal.com" , ptype="unavailable")
188
+ self.xmpp.get_roster()
189
+ self.channels.remove(channelname)
190
+
191
+ def sendtochannel(self, channelname:str, body:str):
192
+ if channelname not in self.channels:
193
+ self.subscribe(channelname)
194
+ self.xmpp.send_message(mto=f"{channelname}@conference.qepal.com", mbody=body, mtype='groupchat')
133
195
 
134
196
  async def loop(self):
135
- # print("[🔄] Initializing connection...")
197
+
136
198
  ssl_ctx = ssl.create_default_context()
137
- ssl_ctx.check_hostname = False # Disable hostname verification
138
- ssl_ctx.verify_mode = ssl.CERT_NONE # Ignore SSL certificate validation
199
+ ssl_ctx.check_hostname = False
200
+ ssl_ctx.verify_mode = ssl.CERT_NONE
139
201
  self.xmpp.ssl_context = ssl_ctx
140
202
 
141
203
  self.xmpp.connect(address=("direct.qepal.com", 5222), disable_starttls=False, force_starttls=True)
142
- self.xmpp.process(forever=True) # Keep the connection alive
204
+ self.xmpp.process(forever=True)
143
205
 
144
206
 
145
207
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: wnox
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: A short description of your package
5
5
  Home-page: https://github.com/arminkardan/pywnox
6
6
  Author: Ethan (Armin) Cardan
@@ -0,0 +1,6 @@
1
+ wnox/__init__.py,sha256=_M92Wza8dl4QeQWdM0ckRtphgyfZs9g4DqwwvgSvOKI,8234
2
+ wnox-0.5.0.dist-info/LICENSE.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ wnox-0.5.0.dist-info/METADATA,sha256=JK1RXI-Ep2tmgbAmGiIkbCCwBMWwyjGrBZ6oXYWrfZE,670
4
+ wnox-0.5.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
+ wnox-0.5.0.dist-info/top_level.txt,sha256=Xm9SC1bx_o6zjvo2FI-3QiZX2PZ_0UBQkGlvfYsnkwc,5
6
+ wnox-0.5.0.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- wnox/__init__.py,sha256=j7NZA4FZiwhE4EAUumAR-8pWweC7Fw-Dt2QHbPCgJu4,6128
2
- wnox-0.3.0.dist-info/LICENSE.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- wnox-0.3.0.dist-info/METADATA,sha256=4jzCO_HyB0cIHeSrEg4MvYuVibx0goO1S_Hgqk2yyJI,670
4
- wnox-0.3.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
- wnox-0.3.0.dist-info/top_level.txt,sha256=Xm9SC1bx_o6zjvo2FI-3QiZX2PZ_0UBQkGlvfYsnkwc,5
6
- wnox-0.3.0.dist-info/RECORD,,
File without changes