wnox 0.1.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
wnox/__init__.py ADDED
@@ -0,0 +1,145 @@
1
+ #%%
2
+ import asyncio
3
+ import nest_asyncio
4
+ import logging
5
+ from slixmpp import ClientXMPP
6
+ import ssl
7
+ import json
8
+ from bson import ObjectId # If you need ObjectId validation
9
+ import requests as r
10
+
11
+ nest_asyncio.apply()
12
+ # logging.basicConfig(level=logging.DEBUG)
13
+ class EventEmitter:
14
+ def __init__(self):
15
+ self._events = {}
16
+
17
+ def on(self, event_name, callback):
18
+ if event_name not in self._events:
19
+ self._events[event_name] = []
20
+ self._events[event_name].append(callback)
21
+
22
+ async def emit(self, event_name, *args, **kwargs):
23
+ if event_name in self._events:
24
+ # Collect the results of all event handlers
25
+ results = []
26
+ for callback in self._events[event_name]:
27
+ result = callback(*args, **kwargs)
28
+ if asyncio.iscoroutinefunction(callback): # If callback is async
29
+ results.append(await result)
30
+ else: # If callback is sync
31
+ results.append(result)
32
+ return results[0]
33
+
34
+ class __WebSocketXMPP(ClientXMPP, EventEmitter):
35
+ def __init__(self, jid, password):
36
+
37
+
38
+ ClientXMPP.__init__(self, jid, password)
39
+ EventEmitter.__init__(self)
40
+ print(f"connecting to {jid} - {password}")
41
+ # self.jid = jid
42
+ self.password = password
43
+ # self.callback = callback # Store the callback function
44
+ self.add_event_handler("session_start", self.start)
45
+ self.add_event_handler("failed_auth", self.on_failed_auth)
46
+ self.add_event_handler("disconnected", self.on_disconnect)
47
+ self.add_event_handler("message", self.on_message) # Add event handler for incoming messages
48
+
49
+ async def start(self, event):
50
+ """Handle session start."""
51
+ print("[bridge] connected.")
52
+ self.send_presence()
53
+ await self.get_roster()
54
+
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
+
59
+ def on_failed_auth(self, event):
60
+ """Handle authentication failure."""
61
+ # print("[❌] Authentication failed. Check username/password.")
62
+
63
+ def on_disconnect(self, event):
64
+ """Handle disconnection and attempt reconnection."""
65
+ # print("[❌] Disconnected from server. Attempting to reconnect...")
66
+ asyncio.create_task(self.reconnect())
67
+
68
+ async def reconnect(self):
69
+ await asyncio.sleep(5) # Wait before reconnecting
70
+ print("[🔄] Reconnecting...")
71
+ self.connect(address=("direct.qepal.com", 5222), disable_starttls=False, force_starttls=True)
72
+ self.process(forever=False)
73
+
74
+ async def on_message(self, stanza):
75
+ """Handle incoming messages."""
76
+ if stanza.tag == "{jabber:client}message":
77
+ body = str(stanza['body'])
78
+ from_jid = str(stanza['from'])
79
+ itsme = from_jid and f"{self.boundjid.bare.split('@')[0]}-{self.boundjid.bare.split('@')[1]}" in from_jid
80
+ itsbro = not itsme and f"{self.boundjid.bare.split('@')[0]}-" in from_jid
81
+ delayed = "urn:xmpp:delay" in str(stanza)
82
+
83
+ if body and not delayed:
84
+ 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
+
90
+ if body.startswith("{"):
91
+ try:
92
+ json_data = json.loads(body)
93
+ if "api" in json_data:
94
+ data = {key: val for key, val in json_data.items() if key != "api"}
95
+ data = {key: val for key, val in data.items() if key != "mid"}
96
+
97
+ if True or len(user_uid) == 24 and ObjectId.is_valid(user_uid):
98
+ result = await self.emit(json_data["api"], data)
99
+ if result == None:
100
+ result = {}
101
+ self.send_message(
102
+ mto=from_jid,
103
+ mbody=json.dumps({**result, "mid": json_data.get("mid")})
104
+ )
105
+ else:
106
+ await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro, "is_app":is_app})
107
+ except json.JSONDecodeError:
108
+ pass
109
+ else:
110
+ await self.emit("message", {"from": from_jid, "body": body, "itsme": itsme, "itsbro": itsbro, "is_app":is_app})
111
+
112
+
113
+
114
+ class App:
115
+ def __init__(self, *, app:str, resource:str, securekey:str, image:str, public:bool=False):
116
+ self.app = app
117
+ self.resource = resource
118
+ self.securekey = securekey
119
+ self.image = image
120
+ self.public = public
121
+
122
+ json = r.post("https://qepal.com/api/bridge/worker/init", json={
123
+ "app":app, "resource":resource, "securekey":securekey, "image":image, "public":public}).json()
124
+
125
+ self.uid = json["uid"]
126
+ self.myjid = self.app + "-" + str(self.uid) + "@qepal.com/" + self.resource
127
+ self.password = json["password"]
128
+ self.xmpp = __WebSocketXMPP(self.myjid, self.password)
129
+
130
+ def on(self, api:str, cb:callable):
131
+ self.xmpp.on(api, cb)
132
+
133
+
134
+ async def loop(self):
135
+ # print("[🔄] Initializing connection...")
136
+ 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
139
+ self.xmpp.ssl_context = ssl_ctx
140
+
141
+ self.xmpp.connect(address=("direct.qepal.com", 5222), disable_starttls=False, force_starttls=True)
142
+ self.xmpp.process(forever=True) # Keep the connection alive
143
+
144
+
145
+
File without changes
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.2
2
+ Name: wnox
3
+ Version: 0.1.0
4
+ Summary: A short description of your package
5
+ Home-page: https://github.com/arminkardan/pywnox
6
+ Author: Ethan (Armin) Cardan
7
+ Author-email: "Ethan (Armin) Cardan" <armin.fire@gmail.com>
8
+ Project-URL: homepage, https://github.com/arminkardan/pywnox
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.6
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE.txt
15
+ Requires-Dist: asyncio
16
+ Requires-Dist: nest_asyncio
17
+ Requires-Dist: logging
18
+ Requires-Dist: slixmpp
19
+ Requires-Dist: ssl
20
+ Requires-Dist: bson
21
+ Requires-Dist: json
22
+ Requires-Dist: requests
23
+ Dynamic: author
24
+ Dynamic: home-page
25
+ Dynamic: requires-python
26
+
27
+ QE nexus client.
@@ -0,0 +1,6 @@
1
+ wnox/__init__.py,sha256=j7NZA4FZiwhE4EAUumAR-8pWweC7Fw-Dt2QHbPCgJu4,6128
2
+ wnox-0.1.0.dist-info/LICENSE.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ wnox-0.1.0.dist-info/METADATA,sha256=xCsnfct854waMtW1yW5vfrWwWcBQzEChG7QC5vFv8mg,812
4
+ wnox-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
+ wnox-0.1.0.dist-info/top_level.txt,sha256=Xm9SC1bx_o6zjvo2FI-3QiZX2PZ_0UBQkGlvfYsnkwc,5
6
+ wnox-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.8.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ wnox