melonsoda 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ ![meronsoda](melon.png)
2
+
3
+ melonsoda is a unblocked games hub with unblockers, games, etc.
4
+
5
+ <br>
6
+
7
+ we have a small set of games, but i am planning to add more in the future
8
+
9
+ ## singlefile
10
+ melonsoda has a variety of single file versions of the website in the `offline/` folder
11
+
12
+ here’s a single table with all files in the folder:
13
+
14
+
15
+ | file | description | pros | cons | download |
16
+ | -------------------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
17
+ | index.html | bundled version of the website (static) | works offline<br>fast load (no external requests)<br>simple deployment | does not update automatically<br>requires manual redownload for changes | [index.html](https://raw.githubusercontent.com/linuxfandudeguy/melonsoda/refs/heads/main/offline/index.html) |
18
+ | selfupdating.html | dynamically updates using axios | always fetches latest version<br>no external cdn dependency | large file size (unminified axios)<br>needs internet connection | [selfupdating.html](https://raw.githubusercontent.com/linuxfandudeguy/melonsoda/refs/heads/main/offline/selfupdating.html) |
19
+ | selfupdating (axios on cdn).html | self-updating version using multiple cdn fallbacks for axios | smaller file size<br>cdn redundancy (tries multiple sources)<br>faster load if cdn works | depends on external cdns<br>some cdns may fail<br>requires internet connection | [selfupdating (axios on cdn).html](https://raw.githubusercontent.com/linuxfandudeguy/melonsoda/refs/heads/main/offline/selfupdating%20(axios%20on%20cdn).html) |
20
+ | selfupdating-protected.html | self-updating version with password protection (**password: homeworksucks**) | restricts access from admins/teachers<br>still updates dynamically | uses unminified axios (large size)<br>viewer-cli does not work<br> | [selfupdating-protected.html](https://raw.githubusercontent.com/linuxfandudeguy/melonsoda/refs/heads/main/offline/selfupdating-protected.html) |
21
+
22
+
23
+
24
+
25
+
26
+
27
+ ## links
28
+
29
+ <a href="https://durokotte.foo.ng/melonsoda/" target="_blank">the main melon</a> this is the main page<br>
30
+ <a href="https://meronsooda.netlify.app/" target="_blank">netlify melon</a> netlify mirror<br>
31
+ <a href="https://raw.githack.com/linuxfandudeguy/melonsoda/main/" target="_blank">totally legit githack</a> not hosted by me but i personally use it so it passes<br>
32
+ <a href="https://learn-french-easy.wasmer.app/" target="_blank">f r e n c h</a> you can learn some very nice french words like le cul (also offline/selfupdating.html is the only page that updates)<br>
33
+ <a href="https://k12-algebra-tutoring-edu-us-resources.pages.dev/" target="_blank">totally real algebra help</a> omg algebra tutoring!1!1!11<br>
34
+ <a href="https://educational-algebra-study-tutor.edgeone.app/" target="_blank">very not sketchy edgeone deploy</a> had to use the sketchy tencent edge service as that wasn't blocked (offline/selfupdating.html is the one served)<br>
35
+ <a href="https://free-french-resources.web.app/" target="_blank">firebase classic</a> firebase deploy (index page does not update but /selfupdating.html updates and also for some reason <br> the official website checking system says the site is not official but it is tho)<br>
36
+ <a href="https://free-french-resources.firebaseapp.com/" target="_blank">firebase alt route</a> alternate firebase deploy<br>
37
+
38
+
39
+ ## links
40
+
41
+ <a href="https://durokotte.foo.ng/melonsoda/" target="_blank">the main melon</a> this is the main page<br>
42
+ <a href="https://meronsooda.netlify.app/" target="_blank">netlify melon</a> netlify mirror<br>
43
+ <a href="https://raw.githack.com/linuxfandudeguy/melonsoda/main/" target="_blank">totally legit githack</a> not hosted by me but i personally use it so it passes<br>
44
+ <a href="https://learn-french-easy.wasmer.app/" target="_blank">f r e n c h</a> you can learn some very nice french words like le cul (also offline/selfupdating.html is the only page that updates)<br>
45
+ <a href="https://k12-algebra-tutoring-edu-us-resources.pages.dev/" target="_blank">totally real algebra help</a> omg algebra tutoring!1!1!11<br>
46
+ <a href="https://educational-algebra-study-tutor.edgeone.app/" target="_blank">very not sketchy edgeone deploy</a> had to use the sketchy tencent edge service as that wasn't blocked (offline/selfupdating.html is the one served)<br>
47
+ <a href="https://free-french-resources.web.app/" target="_blank">firebase classic</a> firebase deploy (index page does not update but /selfupdating.html updates and also for some reason <br> the official website checking system says the site is not official but it is tho)<br>
48
+ <a href="https://free-french-resources.firebaseapp.com/" target="_blank">firebase alt route</a> alternate firebase deploy<br>
49
+
50
+
51
+ ## links
52
+
53
+ <a href="https://durokotte.foo.ng/melonsoda/" target="_blank">the main melon</a> this is the main page<br>
54
+ <a href="https://meronsooda.netlify.app/" target="_blank">netlify melon</a> netlify mirror<br>
55
+ <a href="https://raw.githack.com/linuxfandudeguy/melonsoda/main/" target="_blank">totally legit githack</a> not hosted by me but i personally use it so it passes<br>
56
+ <a href="https://learn-french-easy.wasmer.app/" target="_blank">f r e n c h</a> you can learn some very nice french words like le cul (also offline/selfupdating.html is the only page that updates)<br>
57
+ <a href="https://k12-algebra-tutoring-edu-us-resources.pages.dev/" target="_blank">totally real algebra help</a> omg algebra tutoring!1!1!11<br>
58
+ <a href="https://educational-algebra-study-tutor.edgeone.app/" target="_blank">very not sketchy edgeone deploy</a> had to use the sketchy tencent edge service as that wasn't blocked (offline/selfupdating.html is the one served)<br>
59
+ <a href="https://free-french-resources.web.app/" target="_blank">firebase classic</a> firebase deploy (index page does not update but /selfupdating.html updates and also for some reason <br> the official website checking system says the site is not official but it is tho)<br>
60
+ <a href="https://free-french-resources.firebaseapp.com/" target="_blank">firebase alt route</a> alternate firebase deploy<br>
Binary file
package/build.py ADDED
@@ -0,0 +1,131 @@
1
+ # Credit to https://github.com/nautilus-os/NautilusOS for the original script
2
+ # This script is a edited version of the original script.
3
+ # Licensed under AGPL-3.0 license
4
+
5
+ import base64
6
+ import mimetypes
7
+ import pathlib
8
+ import re
9
+ import urllib.parse
10
+ import urllib.request
11
+ import shutil
12
+
13
+ root = pathlib.Path(__file__).resolve().parent
14
+ index_path = root / "index.html"
15
+ output_dir = root / "offline"
16
+ output_path = output_dir / "index.html"
17
+ placeholder_path = output_dir / "placeholder-deleteme"
18
+ cache = {}
19
+
20
+ # --- Utilities ---
21
+ def fetch_bytes(url):
22
+ if url not in cache:
23
+ req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
24
+ with urllib.request.urlopen(req) as resp:
25
+ cache[url] = resp.read()
26
+ return cache[url]
27
+
28
+ def read_local_bytes(path):
29
+ full_path = root / path.lstrip("/")
30
+ return full_path.read_bytes()
31
+
32
+ def guess_mime(path):
33
+ return mimetypes.guess_type(path)[0] or "application/octet-stream"
34
+
35
+ def to_data_url(data, mime):
36
+ encoded = base64.b64encode(data).decode("ascii")
37
+ return f"data:{mime};base64,{encoded}"
38
+
39
+ # --- CSS Inlining ---
40
+ def inline_remote_css(url):
41
+ css = fetch_bytes(url).decode("utf-8")
42
+ return "<style>\n" + inline_css_assets(css, url) + "\n</style>"
43
+
44
+ def inline_local_css(path):
45
+ full_path = root / path.lstrip("/")
46
+ css = full_path.read_text(encoding="utf-8")
47
+ return "<style>\n" + inline_css_assets(css, full_path) + "\n</style>"
48
+
49
+ def inline_css_assets(css_text, base_path):
50
+ def repl(match):
51
+ target = match.group(1).strip().strip("\"'")
52
+ if target.startswith("data:") or target.startswith("#"):
53
+ return match.group(0)
54
+ # Resolve URL
55
+ asset_url = target
56
+ is_remote = False
57
+ if isinstance(base_path, pathlib.Path):
58
+ asset_path = (base_path.parent / target).resolve()
59
+ if not asset_path.exists():
60
+ print(f"Warning: Asset not found: {asset_path}")
61
+ return match.group(0)
62
+ data = asset_path.read_bytes()
63
+ mime = guess_mime(asset_path)
64
+ else:
65
+ # base_path is remote URL
66
+ asset_url = urllib.parse.urljoin(base_path, target)
67
+ data = fetch_bytes(asset_url)
68
+ mime = guess_mime(asset_url)
69
+ return f"url('{to_data_url(data, mime)}')"
70
+ return re.sub(r"url\(([^)]+)\)", repl, css_text)
71
+
72
+ # --- Script Inlining ---
73
+ def inline_script(match):
74
+ src = match.group(1)
75
+ try:
76
+ if src.startswith("http://") or src.startswith("https://"):
77
+ script_text = fetch_bytes(src).decode("utf-8")
78
+ else:
79
+ script_text = (root / src.lstrip("/")).read_text(encoding="utf-8")
80
+ return f"<script>\n{script_text}\n</script>"
81
+ except Exception as e:
82
+ print(f"Failed to inline script {src}: {e}")
83
+ return match.group(0)
84
+
85
+ # --- Image Inlining ---
86
+ def inline_img(match):
87
+ src = match.group(1)
88
+ if src.startswith("data:"):
89
+ return match.group(0)
90
+ try:
91
+ if src.startswith("http://") or src.startswith("https://"):
92
+ data = fetch_bytes(src)
93
+ else:
94
+ data = (root / src.lstrip("/")).read_bytes()
95
+ mime = guess_mime(src)
96
+ return f'<img src="{to_data_url(data, mime)}"'
97
+ except Exception as e:
98
+ print(f"Failed to inline image {src}: {e}")
99
+ return match.group(0)
100
+
101
+ # --- Read index.html ---
102
+ index_text = index_path.read_text(encoding="utf-8")
103
+
104
+ # --- Replace Stylesheets ---
105
+ link_pattern = re.compile(r'<link\s+[^>]*rel=["\']stylesheet["\'][^>]*href=["\']([^"\']+)["\'][^>]*>', re.IGNORECASE)
106
+ def replace_link(match):
107
+ href = match.group(1)
108
+ if href.startswith("http://") or href.startswith("https://"):
109
+ return inline_remote_css(href)
110
+ else:
111
+ return inline_local_css(href)
112
+ index_text = re.sub(link_pattern, replace_link, index_text)
113
+
114
+ # --- Replace Scripts ---
115
+ script_pattern = re.compile(r'<script\s+[^>]*src=["\']([^"\']+)["\'][^>]*></script>', re.IGNORECASE)
116
+ index_text = re.sub(script_pattern, inline_script, index_text)
117
+
118
+ # --- Replace Images ---
119
+ img_pattern = re.compile(r'<img\s+[^>]*src=["\']([^"\']+)["\']', re.IGNORECASE)
120
+ index_text = re.sub(img_pattern, inline_img, index_text)
121
+
122
+ # --- Output ---
123
+ output_dir.mkdir(parents=True, exist_ok=True)
124
+ if placeholder_path.exists():
125
+ if placeholder_path.is_file():
126
+ placeholder_path.unlink()
127
+ elif placeholder_path.is_dir():
128
+ shutil.rmtree(placeholder_path)
129
+
130
+ output_path.write_text(index_text, encoding="utf-8")
131
+ print(f"Wrote {output_path}")
@@ -0,0 +1,2 @@
1
+ // https://github.com/sandoche/Darkmode.js \\ mit
2
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("darkmode-js",[],t):"object"==typeof exports?exports["darkmode-js"]=t():e["darkmode-js"]=t()}("undefined"!=typeof self?self:this,(function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var o=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};o.get||o.set?Object.defineProperty(t,n,o):t[n]=e[n]}return t.default=e,t}(n(1));var r=o.default;t.default=r,o.IS_BROWSER&&function(e){e.Darkmode=o.default}(window),e.exports=t.default},function(e,t,n){"use strict";function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.IS_BROWSER=void 0;var r="undefined"!=typeof window;t.IS_BROWSER=r;var a=function(){function e(t){if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),r){t=Object.assign({},{bottom:"32px",right:"32px",left:"unset",time:"0.3s",mixColor:"#fff",backgroundColor:"#fff",buttonColorDark:"#100f2c",buttonColorLight:"#fff",label:"",saveInCookies:!0,autoMatchOsTheme:!0},t);var n="\n .darkmode-layer {\n position: fixed;\n pointer-events: none;\n background: ".concat(t.mixColor,";\n transition: all ").concat(t.time," ease;\n mix-blend-mode: difference;\n }\n\n .darkmode-layer--button {\n width: 2.9rem;\n height: 2.9rem;\n border-radius: 50%;\n right: ").concat(t.right,";\n bottom: ").concat(t.bottom,";\n left: ").concat(t.left,";\n }\n\n .darkmode-layer--simple {\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n transform: scale(1) !important;\n }\n\n .darkmode-layer--expanded {\n transform: scale(100);\n border-radius: 0;\n }\n\n .darkmode-layer--no-transition {\n transition: none;\n }\n\n .darkmode-toggle {\n background: ").concat(t.buttonColorDark,";\n width: 3rem;\n height: 3rem;\n position: fixed;\n border-radius: 50%;\n border:none;\n right: ").concat(t.right,";\n bottom: ").concat(t.bottom,";\n left: ").concat(t.left,";\n cursor: pointer;\n transition: all 0.5s ease;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n .darkmode-toggle--white {\n background: ").concat(t.buttonColorLight,";\n }\n\n .darkmode-toggle--inactive {\n display: none;\n }\n\n .darkmode-background {\n background: ").concat(t.backgroundColor,";\n position: fixed;\n pointer-events: none;\n z-index: -10;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n }\n\n img, .darkmode-ignore {\n isolation: isolate;\n display: inline-block;\n }\n\n @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n .darkmode-toggle {display: none !important}\n }\n\n @supports (-ms-ime-align:auto), (-ms-accelerator:true) {\n .darkmode-toggle {display: none !important}\n }\n "),o=document.createElement("div"),a=document.createElement("button"),i=document.createElement("div");a.innerHTML=t.label,a.classList.add("darkmode-toggle--inactive"),o.classList.add("darkmode-layer"),i.classList.add("darkmode-background");var d="true"===window.localStorage.getItem("darkmode"),s=t.autoMatchOsTheme&&window.matchMedia("(prefers-color-scheme: dark)").matches,l=null===window.localStorage.getItem("darkmode");(!0===d&&t.saveInCookies||l&&s)&&(o.classList.add("darkmode-layer--expanded","darkmode-layer--simple","darkmode-layer--no-transition"),a.classList.add("darkmode-toggle--white"),document.body.classList.add("darkmode--activated")),document.body.insertBefore(a,document.body.firstChild),document.body.insertBefore(o,document.body.firstChild),document.body.insertBefore(i,document.body.firstChild),this.addStyle(n),this.button=a,this.layer=o,this.saveInCookies=t.saveInCookies,this.time=t.time}}var t,n,a;return t=e,(n=[{key:"addStyle",value:function(e){var t=document.createElement("link");t.setAttribute("rel","stylesheet"),t.setAttribute("type","text/css"),t.setAttribute("href","data:text/css;charset=UTF-8,"+encodeURIComponent(e)),document.head.appendChild(t)}},{key:"showWidget",value:function(){var e=this;if(r){var t=this.button,n=this.layer,o=1e3*parseFloat(this.time);t.classList.add("darkmode-toggle"),t.classList.remove("darkmode-toggle--inactive"),t.setAttribute("aria-label","Activate dark mode"),t.setAttribute("aria-checked","false"),t.setAttribute("role","checkbox"),n.classList.add("darkmode-layer--button"),t.addEventListener("click",(function(){var r=e.isActivated();r?(n.classList.remove("darkmode-layer--simple"),t.setAttribute("disabled",!0),setTimeout((function(){n.classList.remove("darkmode-layer--no-transition"),n.classList.remove("darkmode-layer--expanded"),t.removeAttribute("disabled")}),1)):(n.classList.add("darkmode-layer--expanded"),t.setAttribute("disabled",!0),setTimeout((function(){n.classList.add("darkmode-layer--no-transition"),n.classList.add("darkmode-layer--simple"),t.removeAttribute("disabled")}),o)),t.classList.toggle("darkmode-toggle--white"),document.body.classList.toggle("darkmode--activated"),window.localStorage.setItem("darkmode",!r)}))}}},{key:"toggle",value:function(){if(r){var e=this.layer,t=this.isActivated(),n=this.button;e.classList.toggle("darkmode-layer--simple"),document.body.classList.toggle("darkmode--activated"),window.localStorage.setItem("darkmode",!t),n.setAttribute("aria-label","De-activate dark mode"),n.setAttribute("aria-checked","true")}}},{key:"isActivated",value:function(){return r?document.body.classList.contains("darkmode--activated"):null}}])&&o(t.prototype,n),a&&o(t,a),e}();t.default=a}])}));
package/firebase.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "hosting": {
3
+ "public": "offline",
4
+ "ignore": [
5
+ "firebase.json",
6
+ "**/.*",
7
+ "**/node_modules/**"
8
+ ]
9
+ }
10
+ }