hungerlib 4.24.dev14__tar.gz → 4.24.2__tar.gz

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 (41) hide show
  1. {hungerlib-4.24.dev14/src/hungerlib.egg-info → hungerlib-4.24.2}/PKG-INFO +8 -6
  2. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/pyproject.toml +8 -6
  3. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/__init__.py +14 -2
  4. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/email/manager.py +6 -11
  5. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/messagerouter.py +21 -1
  6. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/servers/generic.py +3 -2
  7. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/utils/__init__.py +4 -0
  8. hungerlib-4.24.2/src/hungerlib/utils/buffer.py +20 -0
  9. hungerlib-4.24.2/src/hungerlib/utils/convert.py +61 -0
  10. hungerlib-4.24.2/src/hungerlib/webhook/__init__.py +4 -0
  11. hungerlib-4.24.2/src/hungerlib/webhook/client.py +20 -0
  12. hungerlib-4.24.2/src/hungerlib/webhook/server.py +56 -0
  13. {hungerlib-4.24.dev14 → hungerlib-4.24.2/src/hungerlib.egg-info}/PKG-INFO +8 -6
  14. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib.egg-info/SOURCES.txt +6 -2
  15. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib.egg-info/requires.txt +3 -1
  16. hungerlib-4.24.dev14/src/hungerlib/discord_bot_webhook.py +0 -14
  17. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/LICENSE +0 -0
  18. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/README.md +0 -0
  19. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/setup.cfg +0 -0
  20. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/__init__.py +0 -0
  21. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/backups.py +0 -0
  22. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/command.py +0 -0
  23. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/databases.py +0 -0
  24. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/filemanager.py +0 -0
  25. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/schedule.py +0 -0
  26. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/api/startup.py +0 -0
  27. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/bridgeclient.py +0 -0
  28. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/configloader.py +0 -0
  29. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/email/__init__.py +0 -0
  30. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/email/client.py +0 -0
  31. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/email/email_templates/restart.html +0 -0
  32. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/email/message.py +0 -0
  33. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/panel.py +0 -0
  34. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/servers/__init__.py +0 -0
  35. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/servers/minecraft.py +0 -0
  36. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/utils/exceptions.py +0 -0
  37. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/utils/time.py +0 -0
  38. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/utils/utils.py +0 -0
  39. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib/validator.py +0 -0
  40. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib.egg-info/dependency_links.txt +0 -0
  41. {hungerlib-4.24.dev14 → hungerlib-4.24.2}/src/hungerlib.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hungerlib
3
- Version: 4.24.dev14
3
+ Version: 4.24.2
4
4
  Summary: Powerful automation library for Pterodactyl.
5
5
  Author: iFamished
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/iFamishedX/HungerLib
8
- Project-URL: Documentation, https://github.com/iFamishedX/HungerLib
9
- Project-URL: Source, https://github.com/iFamishedX/HungerLib
10
- Project-URL: Issues, https://github.com/iFamishedX/HungerLib/issues
7
+ Project-URL: Homepage, https://github.com/iFamished/HungerLib
8
+ Project-URL: Documentation, https://github.com/iFamished/HungerLib
9
+ Project-URL: Source, https://github.com/iFamished/HungerLib
10
+ Project-URL: Issues, https://github.com/iFamished/HungerLib/issues
11
11
  Keywords: pterodactyl,minecraft,automation,rcon,server-management,hungerlib,hungernet
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.10
@@ -23,10 +23,12 @@ Requires-Python: >=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: requests
26
- Requires-Dist: mcrcon
27
26
  Requires-Dist: PyYaml
28
27
  Requires-Dist: mapres
29
28
  Requires-Dist: jinja2
29
+ Requires-Dist: cloudflare
30
+ Requires-Dist: uvicorn
31
+ Requires-Dist: fastapi
30
32
  Dynamic: license-file
31
33
 
32
34
  # HungerLib
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "hungerlib"
10
- version = "4.24-dev.14"
10
+ version = "4.24.2"
11
11
  description = "Powerful automation library for Pterodactyl."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.9"
@@ -25,10 +25,12 @@ keywords = [
25
25
  ]
26
26
  dependencies = [
27
27
  "requests",
28
- "mcrcon",
29
28
  "PyYaml",
30
29
  "mapres",
31
30
  "jinja2",
31
+ "cloudflare",
32
+ "uvicorn",
33
+ "fastapi",
32
34
  ]
33
35
  classifiers = [
34
36
  "Programming Language :: Python :: 3",
@@ -47,10 +49,10 @@ classifiers = [
47
49
  text = "MIT"
48
50
 
49
51
  [project.urls]
50
- Homepage = "https://github.com/iFamishedX/HungerLib"
51
- Documentation = "https://github.com/iFamishedX/HungerLib"
52
- Source = "https://github.com/iFamishedX/HungerLib"
53
- Issues = "https://github.com/iFamishedX/HungerLib/issues"
52
+ Homepage = "https://github.com/iFamished/HungerLib"
53
+ Documentation = "https://github.com/iFamished/HungerLib"
54
+ Source = "https://github.com/iFamished/HungerLib"
55
+ Issues = "https://github.com/iFamished/HungerLib/issues"
54
56
 
55
57
  [tool.setuptools]
56
58
  include-package-data = true
@@ -13,8 +13,8 @@ from .messagerouter import MessageRouter
13
13
  from .panel import Panel
14
14
  from .servers import GenericServer, MinecraftServer
15
15
  from .bridgeclient import BridgeClient
16
- from .discord_bot_webhook import DiscordBotWebhook
17
16
  from .email import Email, EmailManager, EmailClient
17
+ from .webhook import WebhookClient, WebhookServer
18
18
  from .validator import (
19
19
  Validator,
20
20
  ValidationError,
@@ -34,6 +34,8 @@ from .utils import (
34
34
  Snapshot,
35
35
  clearTerminal,
36
36
  validateAll,
37
+ Buffer,
38
+ convert,
37
39
 
38
40
  # exceptions
39
41
  HungerLibError,
@@ -53,6 +55,8 @@ utils = SimpleNamespace(
53
55
  Snapshot = Snapshot,
54
56
  clearTerminal = clearTerminal,
55
57
  validateAll = validateAll,
58
+ Buffer = Buffer,
59
+ convert = convert,
56
60
  )
57
61
 
58
62
  servers = SimpleNamespace(
@@ -61,6 +65,10 @@ servers = SimpleNamespace(
61
65
  Minecraft = MinecraftServer,
62
66
  )
63
67
 
68
+ webhook = SimpleNamespace(
69
+ Client = WebhookClient,
70
+ Server = WebhookServer,
71
+ )
64
72
 
65
73
 
66
74
  __all__ = [
@@ -73,7 +81,6 @@ __all__ = [
73
81
  'GenericServer',
74
82
  'MinecraftServer',
75
83
  'BridgeClient',
76
- 'DiscordBotWebhook',
77
84
  'Validator',
78
85
  'Email',
79
86
  'EmailManager',
@@ -89,6 +96,10 @@ __all__ = [
89
96
  'Snapshot',
90
97
  'clearTerminal',
91
98
  'validateAll',
99
+ 'WebhookServer',
100
+ 'WebhookClient',
101
+ 'Buffer',
102
+ 'convert',
92
103
 
93
104
  # errors
94
105
  'ValidationError',
@@ -105,4 +116,5 @@ __all__ = [
105
116
  # namespaces
106
117
  'utils',
107
118
  'servers',
119
+ 'webhook',
108
120
  ]
@@ -3,26 +3,24 @@ import pathlib
3
3
  from cloudflare import Cloudflare
4
4
  from .message import Email
5
5
 
6
- # Templates live in: src/hungerlib/email/email_templates
7
6
  TEMPLATE_DIR = pathlib.Path(__file__).resolve().parent / "email_templates"
8
7
 
9
8
  class EmailManager:
10
- """
9
+ '''
11
10
  Backend email system.
12
11
  Holds API token and account ID.
13
12
  Sends emails created by EmailClient.
14
- """
15
-
13
+ '''
16
14
  def __init__(self, api_token: str, account_id: str):
17
15
  self.client = Cloudflare(api_token=api_token)
18
16
  self.account_id = account_id
19
17
 
20
- # Jinja2 environment configured for HTML emails
18
+ # Jinja2 configured to NOT alter whitespace or escape HTML
21
19
  self.jinja = Environment(
22
20
  loader=FileSystemLoader(str(TEMPLATE_DIR)),
23
- autoescape=False, # Cloudflare rejects escaped HTML
24
- trim_blocks=False, # preserve whitespace
25
- lstrip_blocks=False # preserve indentation
21
+ autoescape=False,
22
+ trim_blocks=False,
23
+ lstrip_blocks=False
26
24
  )
27
25
 
28
26
  def render_template(self, template: str, ctx: dict) -> str:
@@ -45,9 +43,6 @@ class EmailManager:
45
43
  payload["text"] = email.text
46
44
 
47
45
  if email.html:
48
- print("=== FINAL HTML SENT TO CLOUDFLARE ===")
49
- print(email.html)
50
- print("=====================================")
51
46
  payload["html"] = email.html
52
47
 
53
48
  if email.cc:
@@ -3,6 +3,7 @@ import logging
3
3
  from pathlib import Path
4
4
  from datetime import datetime
5
5
  from .utils.exceptions import InvalidLevelError
6
+ from .utils.buffer import Buffer
6
7
 
7
8
  class MessageRouter:
8
9
  def __init__(
@@ -20,6 +21,9 @@ class MessageRouter:
20
21
  info_prefix = '<white>[%hh%:%mm%:%ss%] [INFO]: ',
21
22
  warn_prefix = '<yellow>[%hh%:%mm%:%ss%] [WARN]: ',
22
23
  error_prefix = '<red>[%hh%:%mm%:%ss%] [ERROR]: ',
24
+
25
+ buffer_enabled = False,
26
+ origin_output = True
23
27
  ):
24
28
  self.name = name
25
29
  self.Servers = Servers
@@ -59,6 +63,14 @@ class MessageRouter:
59
63
  'filelog': self.filelog
60
64
  }
61
65
 
66
+ # buffering
67
+ self.buffer = Buffer(enabled=buffer_enabled)
68
+ self.origin_output = origin_output
69
+
70
+
71
+ def enableOriginOutput(self): self.origin_output = True
72
+ def disableOriginOutput(self): self.origin_output = False
73
+
62
74
  def registerLevel(self, name, prefix, file_method=None, routes=None):
63
75
  lvl = name.lower()
64
76
  self.custom_levels[lvl] = {
@@ -139,7 +151,15 @@ class MessageRouter:
139
151
  mapped = self._format(text, maps, **ctx)
140
152
  prefix = self._resolve_prefix(level, ctx)
141
153
  msg = prefix + mapped
142
- print(msg)
154
+
155
+ # buffer logic
156
+ if self.buffer.enabled:
157
+ self.buffer.captured.append(msg)
158
+
159
+ # origin output check
160
+ if self.origin_output:
161
+ print(msg)
162
+
143
163
  return msg
144
164
 
145
165
  def destination(self, text, level='info', extra_maps=None, override_maps=None, **ctx):
@@ -69,9 +69,10 @@ class GenericServer:
69
69
  uptime = self.resources().get('uptime')
70
70
  if uptime is None:
71
71
  return None
72
- seconds = uptime // 1000
73
72
  if not formatted:
74
- return seconds
73
+ # return seconds # returns seconds
74
+ return uptime # returns miliseconds
75
+ seconds = uptime // 1000
75
76
  hours = seconds // 3600
76
77
  minutes = (seconds % 3600) // 60
77
78
  secs = seconds % 60
@@ -1,4 +1,6 @@
1
+ from .buffer import Buffer
1
2
  from .utils import Snapshot, clearTerminal, validateAll
3
+ from .convert import convert
2
4
  from .exceptions import (
3
5
  HungerLibError,
4
6
  InvalidLevelError,
@@ -24,6 +26,8 @@ __all__ = [
24
26
  'Snapshot',
25
27
  'clearTerminal',
26
28
  'validateAll',
29
+ 'Buffer',
30
+ 'convert',
27
31
 
28
32
  # exceptions
29
33
  'HungerLibError',
@@ -0,0 +1,20 @@
1
+ class Buffer:
2
+ def __init__(self, enabled=True):
3
+ self.enabled = enabled
4
+ self.captured = []
5
+
6
+ def enable(self): self.enabled = True
7
+
8
+ def disable(self): self.enabled = False
9
+
10
+ def toggle(self): self.enabled = not self.enabled
11
+
12
+ def clear(self): self.captured = []
13
+
14
+ def printCaptured(self):
15
+ for msg in self.captured:
16
+ print(msg)
17
+
18
+ def flush(self):
19
+ self.printCaptured()
20
+ self.clear()
@@ -0,0 +1,61 @@
1
+ from types import SimpleNamespace
2
+ from mapres import datamap, res
3
+
4
+
5
+ @datamap.pipes
6
+ class TimeUnits:
7
+ ns: float = 1e-9
8
+ us: float = 1e-6
9
+ ms: float = 1e-3
10
+ s: float = 1
11
+ min: float = 60
12
+ h: float = 3600
13
+ day: float = 86400
14
+ time_units = TimeUnits()
15
+
16
+
17
+ @datamap.pipes
18
+ class ByteUnits:
19
+ # decimal
20
+ b: int = 1
21
+ kb: int = 1_000
22
+ mb: int = 1_000_000
23
+ gb: int = 1_000_000_000
24
+ tb: int = 1_000_000_000_000
25
+
26
+ # binary
27
+ kib: int = 1024
28
+ mib: int = 1024**2
29
+ gib: int = 1024**3
30
+ tib: int = 1024**4
31
+ byte_units = ByteUnits()
32
+
33
+
34
+ def _time(value, src, dst, rounding=None):
35
+ value = float(value)
36
+
37
+ src_factor = float(getattr(time_units, src))
38
+ dst_factor = float(getattr(time_units, dst))
39
+
40
+ base = value * src_factor
41
+ result = base / dst_factor
42
+
43
+ return round(result, rounding) if rounding is not None else result
44
+
45
+
46
+ def _byte(value, src, dst, rounding=None):
47
+ value = float(value)
48
+
49
+ src_factor = float(getattr(byte_units, src))
50
+ dst_factor = float(getattr(byte_units, dst))
51
+
52
+ base = value * src_factor
53
+ result = base / dst_factor
54
+
55
+ return round(result, rounding) if rounding is not None else result
56
+
57
+
58
+ convert = SimpleNamespace(
59
+ time=_time,
60
+ byte=_byte,
61
+ )
@@ -0,0 +1,4 @@
1
+ from .server import WebhookServer
2
+ from .client import WebhookClient
3
+
4
+ __all__ = ["WebhookServer", "WebhookClient"]
@@ -0,0 +1,20 @@
1
+ import requests
2
+
3
+ class WebhookClient:
4
+ def __init__(self, url: str, token: str, timeout: int = 5):
5
+ self.url = url
6
+ self.token = token
7
+ self.timeout = timeout
8
+
9
+ def send(self, event: str, **ctx):
10
+ payload = {'event': event, **ctx}
11
+
12
+ resp = requests.post(
13
+ self.url,
14
+ json=payload,
15
+ headers={'x-webhook-token': self.token},
16
+ timeout=self.timeout
17
+ )
18
+
19
+ resp.raise_for_status()
20
+ return resp.json()
@@ -0,0 +1,56 @@
1
+ import uvicorn
2
+ from fastapi import FastAPI, Request, Header, HTTPException
3
+
4
+ class WebhookServer:
5
+ def __init__(self, port: int, token: str, host: str = "0.0.0.0", logLevel: str = "info"):
6
+ self.port = port
7
+ self.token = token
8
+ self.host = host
9
+ self.logLevel = logLevel
10
+
11
+ self.app = FastAPI()
12
+ self._server = None
13
+
14
+ # routing tables
15
+ self._endpointHandlers: dict[str, callable] = {}
16
+ self._eventHandlers: dict[str, callable] = {}
17
+
18
+ def addEndpoint(self, path: str, handler: callable):
19
+ # register endpoint
20
+ self._endpointHandlers[path] = handler
21
+
22
+ @self.app.post(path)
23
+ async def _endpoint(request: Request, x_webhook_token: str | None = Header(None)):
24
+ if x_webhook_token != self.token:
25
+ raise HTTPException(status_code=401, detail="invalid token")
26
+
27
+ data = await request.json()
28
+ event = (data.get("event") or "").lower()
29
+
30
+ # endpoint handler
31
+ await handler(event, data)
32
+
33
+ # event handler
34
+ if event in self._eventHandlers:
35
+ await self._eventHandlers[event](data)
36
+
37
+ return {"status": "ok"}
38
+
39
+ def addHandler(self, event: str, handler: callable):
40
+ # register event handler
41
+ self._eventHandlers[event.lower()] = handler
42
+
43
+ async def start(self):
44
+ config = uvicorn.Config(
45
+ self.app,
46
+ host=self.host,
47
+ port=self.port,
48
+ log_level=self.logLevel
49
+ )
50
+ self._server = uvicorn.Server(config)
51
+ await self._server.serve()
52
+
53
+ async def stop(self):
54
+ # stop server
55
+ if self._server:
56
+ self._server.should_exit = True
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hungerlib
3
- Version: 4.24.dev14
3
+ Version: 4.24.2
4
4
  Summary: Powerful automation library for Pterodactyl.
5
5
  Author: iFamished
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/iFamishedX/HungerLib
8
- Project-URL: Documentation, https://github.com/iFamishedX/HungerLib
9
- Project-URL: Source, https://github.com/iFamishedX/HungerLib
10
- Project-URL: Issues, https://github.com/iFamishedX/HungerLib/issues
7
+ Project-URL: Homepage, https://github.com/iFamished/HungerLib
8
+ Project-URL: Documentation, https://github.com/iFamished/HungerLib
9
+ Project-URL: Source, https://github.com/iFamished/HungerLib
10
+ Project-URL: Issues, https://github.com/iFamished/HungerLib/issues
11
11
  Keywords: pterodactyl,minecraft,automation,rcon,server-management,hungerlib,hungernet
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.10
@@ -23,10 +23,12 @@ Requires-Python: >=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: requests
26
- Requires-Dist: mcrcon
27
26
  Requires-Dist: PyYaml
28
27
  Requires-Dist: mapres
29
28
  Requires-Dist: jinja2
29
+ Requires-Dist: cloudflare
30
+ Requires-Dist: uvicorn
31
+ Requires-Dist: fastapi
30
32
  Dynamic: license-file
31
33
 
32
34
  # HungerLib
@@ -4,7 +4,6 @@ pyproject.toml
4
4
  src/hungerlib/__init__.py
5
5
  src/hungerlib/bridgeclient.py
6
6
  src/hungerlib/configloader.py
7
- src/hungerlib/discord_bot_webhook.py
8
7
  src/hungerlib/messagerouter.py
9
8
  src/hungerlib/panel.py
10
9
  src/hungerlib/validator.py
@@ -29,6 +28,11 @@ src/hungerlib/servers/__init__.py
29
28
  src/hungerlib/servers/generic.py
30
29
  src/hungerlib/servers/minecraft.py
31
30
  src/hungerlib/utils/__init__.py
31
+ src/hungerlib/utils/buffer.py
32
+ src/hungerlib/utils/convert.py
32
33
  src/hungerlib/utils/exceptions.py
33
34
  src/hungerlib/utils/time.py
34
- src/hungerlib/utils/utils.py
35
+ src/hungerlib/utils/utils.py
36
+ src/hungerlib/webhook/__init__.py
37
+ src/hungerlib/webhook/client.py
38
+ src/hungerlib/webhook/server.py
@@ -1,5 +1,7 @@
1
1
  requests
2
- mcrcon
3
2
  PyYaml
4
3
  mapres
5
4
  jinja2
5
+ cloudflare
6
+ uvicorn
7
+ fastapi
@@ -1,14 +0,0 @@
1
- import requests
2
-
3
- class DiscordBotWebhook:
4
- def __init__(self, url: str, token: str):
5
- self.url = url
6
- self.token = token
7
-
8
- def send(self, event: str, **ctx):
9
- requests.post(
10
- self.url,
11
- json={"event": event, **ctx},
12
- headers={"X-Webhook-Token": self.token},
13
- timeout=5
14
- ).raise_for_status()
File without changes
File without changes
File without changes