Skip to content

Commit c969350

Browse files
committedAug 11, 2024
QoL features & fixes
1 parent fc3d187 commit c969350

9 files changed

+76
-44
lines changed
 

‎TODO.md

+32-11
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ List of properties which should be editable somewhere, and handled if necessary
55
| Status | Meaning
66
| --- | ---
77
| ❌ | Not implemented but planned
8+
| 🟨 | Partly implemented
89
| ✅ | Implemented
9-
| ⛔ | Not planned
10+
| ⛔ | Not planned or impossible due to missing information
1011

1112
## User data
1213

14+
`/users/@me/`
15+
1316
| Status | Field | Type | Notes
1417
| --- | --- | --- | ---
1518
| ✅ | username | string - Constraints: 1 to 100 chars
@@ -23,34 +26,38 @@ List of properties which should be editable somewhere, and handled if necessary
2326

2427
## User profile
2528

29+
`/users/{id}/profile/`
30+
2631
| Status | Field | Type | Notes
2732
| --- | --- | --- | ---
2833
| ✅ | bio | string
2934
| ❌ | accent_color | integer┃null
3035
| ❌ | banner | string┃null
3136
| ✅ | pronouns | string
32-
| ❌ | theme_colors | [{missing-type-info}] - Min Items: 2 Max Items: 2
37+
| ❌ | theme_colors | [integer, integer]
3338

3439
## User settings
3540

41+
`/users/@me/settings/`
42+
3643
| Status | Field | Type | Notes
3744
| --- | --- | --- | ---
38-
| ❌ | status | enum - Allowed: dnd┃idle┃invisible┃offline┃online
45+
| ❌ | status | string - one of: dnd┃idle┃invisible┃online
3946
| ❌ | afk_timeout | integer
4047
| ⛔ | allow_accessibility_detection | boolean | What's this for?
4148
| ❌ | animate_emoji | boolean
4249
| ❌ | animate_stickers | integer
4350
| ⛔ | contact_sync_enabled | boolean | Not possible in Web
4451
| ❌ | convert_emoticons | boolean
45-
| ❌ | custom_status | object - ANY OF: 1: object: emoji_id: string, emoji_name: string, expires_at: integer, text: string; 2: null
46-
| | default_guilds_restricted | boolean
52+
| ❌ | custom_status | object - one of: 1: object: emoji_id: string, emoji_name: string, expires_at: integer, text: string; 2: null
53+
| | default_guilds_restricted | boolean | What's this for?
4754
| ⛔ | detect_platform_accounts | boolean | What's this for?
4855
| ❌ | developer_mode | boolean
4956
| ⛔ | disable_games_tab | boolean | No use in SB
5057
| ❌ | enable_tts_command | boolean
5158
| ❌ | explicit_content_filter | integer
5259
| ⛔ | friend_discovery_flags | integer | What's this for?
53-
| | friend_source_flags | object - all*: boolean
60+
| | friend_source_flags | object - all*: boolean | What's this for?
5461
| ⛔ | gateway_connected | boolean | What's this for?
5562
| ❌ | gif_auto_play | boolean
5663
| ❌ | guild_folders | array of object: color*: integer, guild_ids*: [string], id*: integer, name*: string, guild_positions: [string]
@@ -61,25 +68,39 @@ List of properties which should be editable somewhere, and handled if necessary
6168
| ⛔ | native_phone_integration_enabled | boolean | What's this for?
6269
| ❌ | render_embeds | boolean
6370
| ❌ | render_reactions | boolean
64-
| | restricted_guilds | [string]
71+
| | restricted_guilds | [string] | What's this for?
6572
| ⛔ | show_current_game | boolean | Not possible in Web
6673
| ⛔ | stream_notifications_enabled | boolean | What's this for?
67-
| ✅ | theme | enum - Allowed: dark┃light
74+
| ✅ | theme | string - one of: dark┃light
6875
| ❌ | timezone_offset | integer
6976
| ❌ | view_nsfw_guilds | boolean
7077

7178
## Guild settings
7279

80+
`/users/@me/guilds/{guild_id}/settings/`
81+
7382
| Status | Field | Type | Notes
7483
| --- | --- | --- | ---
7584
| ❌ | channel_overrides | object: [any-key]: object: message_notifications*: integer; mute_config*: object: end_time*: integer, selected_time_window*: integer, muted*: boolean, channel_id*: string┃null
7685
| ❌ | message_notifications | integer
7786
| ❌ | mobile_push | boolean
78-
| ❌ | mute_config | object - ANY OF: 1: object: end_time*: integer, selected_time_window*: integer; 2: null
87+
| ❌ | mute_config | object - one of: 1: object: end_time*: integer, selected_time_window*: integer; 2: null
7988
| ❌ | muted | boolean
8089
| ❌ | suppress_everyone | boolean
8190
| ❌ | suppress_roles | boolean
82-
| | flags | integer | Which flags?
91+
| | flags | integer | Which flags?
8392
| ❌ | mute_scheduled_events | boolean
8493
| ❌ | hide_muted_channels | boolean
85-
| ❌ | notify_highlights | number
94+
| ⛔ | notify_highlights | number | What's this for?
95+
96+
## Guild member settings
97+
98+
`/guilds/{guild_id}/profile/{member_id}`
99+
100+
| Status | Field | Type | Notes
101+
| --- | --- | --- | ---
102+
| ❌ | banner | string┃null
103+
| ❌ | nick | string
104+
| ❌ | bio | string
105+
| ❌ | pronouns | string
106+
| ❌ | theme_colors | [integer, integer]

‎index.js

+17-10
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,29 @@ app.use("/", (req, res) => {
5656
const reqPath = req.path.replace(/[^\w.-]/g, "")
5757
if (reqPath.length == 0) return res.sendFile(path.join(__dirname, "webpage", "index.html"))
5858

59-
if (fs.existsSync(path.join(__dirname, "webpage", reqPath))) res.sendFile(path.join(__dirname, "webpage", reqPath))
60-
else if (fs.existsSync(path.join(__dirname, "webpage", "font", reqPath.replace("font", "")))) {
61-
res.sendFile(path.join(__dirname, "webpage", "font", reqPath.replace("font", "")), {
59+
if (reqPath.startsWith("channels") || reqPath.startsWith("invite")) return res.sendFile(path.join(__dirname, "webpage", "index.html"))
60+
if (reqPath == "login") return res.sendFile(path.join(__dirname, "webpage", "login.html"))
61+
if (reqPath == "register") return res.sendFile(path.join(__dirname, "webpage", "register.html"))
62+
63+
if (!/^[\w-]+\.\w+$/.test(reqPath)) {
64+
res.status(400).send("Invalid path!")
65+
return console.warn("Invalid path requested: " + reqPath + " | " + req.originalUrl)
66+
}
67+
68+
if (fs.existsSync(path.join(__dirname, "webpage", reqPath))) return res.sendFile(path.join(__dirname, "webpage", reqPath))
69+
if (fs.existsSync(path.join(__dirname, "webpage", "font", reqPath.replace("font", ""))))
70+
return res.sendFile(path.join(__dirname, "webpage", "font", reqPath.replace("font", "")), {
6271
maxAge: 1000 * 60 * 60 * 24 * 90
6372
})
64-
} else if (fs.existsSync(path.join(__dirname, "webpage", "icons", "bootstrap", reqPath.replace("iconsbootstrap", "")))) {
65-
res.sendFile(path.join(__dirname, "webpage", "icons", "bootstrap", reqPath.replace("iconsbootstrap", "")), {
73+
if (fs.existsSync(path.join(__dirname, "webpage", "icons", "bootstrap", reqPath.replace("iconsbootstrap", ""))))
74+
return res.sendFile(path.join(__dirname, "webpage", "icons", "bootstrap", reqPath.replace("iconsbootstrap", "")), {
6675
maxAge: 1000 * 60 * 60 * 24
6776
})
68-
} else if (fs.existsSync(path.join(__dirname, "webpage", "icons", reqPath.replace("icons", "")))) {
69-
res.sendFile(path.join(__dirname, "webpage", "icons", reqPath.replace("icons", "")), {
77+
if (fs.existsSync(path.join(__dirname, "webpage", "icons", reqPath.replace("icons", ""))))
78+
return res.sendFile(path.join(__dirname, "webpage", "icons", reqPath.replace("icons", "")), {
7079
maxAge: 1000 * 60 * 60 * 24
7180
})
72-
} else if (fs.existsSync(path.join(__dirname, "webpage", reqPath + ".html"))) res.sendFile(path.join(__dirname, "webpage", reqPath + ".html"))
73-
else if (/^connections[a-z]{1,30}callback$/.test(reqPath)) res.sendFile(path.join(__dirname, "webpage", "connections.html"))
74-
else res.sendFile(path.join(__dirname, "webpage", "index.html"))
81+
if (/^connections[a-z]{1,30}callback$/.test(reqPath)) return res.sendFile(path.join(__dirname, "webpage", "connections.html"))
7582
})
7683

7784
const PORT = process.env.PORT || 25512

‎package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "jankclient",
33
"version": "0.1.0",
4-
"description": "A SpaceBar Client written in JS, HTML and CSS. To run, clone the repo and do either `node index.js` or `bun index.js`. To access Jank Client after init simply go to http://localhost:8080/login and login with your username and password.",
4+
"description": "A SpaceBar Client written in JS, HTML and CSS. To run, clone the repo and run `npm start`. To access Jank Client after init simply go to http://localhost:8080/login and login with your username and password.",
55
"main": "index.js",
66
"scripts": {
7-
"start": "node index.js",
7+
"start": "node .",
88
"minify": "node minify.js",
99
"taiko": "taiko",
1010
"test": "taiko test.js",

‎webpage/guild.js

+14-14
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ class Guild {
168168
break
169169
}
170170
}
171-
if (!html) return
172171

172+
if (!html) return
173173
if (read) html.children[0].classList.remove("notiunread")
174174
else html.children[0].classList.add("notiunread")
175175
}
@@ -376,29 +376,29 @@ class Guild {
376376
noti.classList.add("unread")
377377
divy.append(noti)
378378
this.localuser.guildhtml.set(this.id, divy)
379-
if (this.properties.icon === null) {
380-
const div = document.createElement("div")
381-
div.textContent = this.properties.name.split(" ").map(e => e[0]).join("")
382-
div.classList.add("blankserver", "servericon")
383-
divy.appendChild(div)
384-
div.onclick = () => {
385-
this.loadGuild()
386-
this.loadChannel()
387-
}
388-
Guild.contextmenu.bind(div, this)
389-
} else {
379+
if (this.properties.icon) {
390380
const img = document.createElement("img")
391381
img.classList.add("pfp", "servericon")
392382
img.crossOrigin = "anonymous"
393383
img.src = instance.cdn + "/icons/" + this.properties.id + "/" + this.properties.icon + ".png?size=48"
394384
img.alt = "Server: " + this.properties.name
395385
divy.appendChild(img)
396386

397-
img.onclick = () => {
387+
img.addEventListener("click", () => {
398388
this.loadGuild()
399389
this.loadChannel()
400-
}
390+
})
401391
Guild.contextmenu.bind(img, this)
392+
} else {
393+
const div = document.createElement("div")
394+
div.textContent = this.properties.name.replace(/'s /g, " ").replace(/\w+/g, word => word[0]).replace(/\s/g, "")
395+
div.classList.add("blankserver", "servericon")
396+
divy.appendChild(div)
397+
div.addEventListener("click", () => {
398+
this.loadGuild()
399+
this.loadChannel()
400+
})
401+
Guild.contextmenu.bind(div, this)
402402
}
403403
return divy
404404
}

‎webpage/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ document.addEventListener("DOMContentLoaded", async () => {
7777
users.currentuser = thing.uid
7878
localStorage.setItem("userinfos", JSON.stringify(users))
7979
thisuser.initwebsocket().then(() => {
80+
if (Contextmenu.currentmenu != "") Contextmenu.currentmenu.remove()
8081
thisuser.loaduser()
8182
thisuser.init()
8283
document.getElementById("loading").classList.add("doneloading")

‎webpage/service.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ self.addEventListener("fetch", event => {
6969

7070
const responseFromCache = await cache.match(isindexhtml(event.request.url) ? "/index" : event.request)
7171
if (responseFromCache && (
72-
url.pathname == "/manifest.json" || url.pathname == "/logo.svg" ||
73-
url.pathname.startsWith("/icons/") || url.pathname.startsWith("/font/")
72+
url.pathname == "/emoji.bin" ||
73+
url.pathname == "/favicon.ico" || url.pathname == "/logo.svg" || url.pathname == "/logo.webp" ||
74+
url.pathname == "/manifest.json" ||
75+
url.pathname.startsWith("/font/") || url.pathname.startsWith("/icons/")
7476
)) return responseFromCache
75-
else if (responseFromCache) console.log("Found a cached response for " + (isindexhtml(event.request.url) ? "/index" : event.request.url))
77+
if (responseFromCache) console.log("Found a cached response for " + (isindexhtml(event.request.url) ? "/index" : url.pathname))
7678

7779
const responseFromNetwork = await fetch(isindexhtml(event.request.url) ? "/index" : event.request)
7880
cache.put(isindexhtml(event.request.url) ? "/index" : event.request, responseFromNetwork.clone())

‎webpage/settings.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ class RoleList extends Buttons {
474474
}
475475
handleString(str) {
476476
this.curid = str
477-
const perm = this.permissions.find(_ => _[0].id === str)[1]
477+
const perm = this.permissions.find(p => p[0].id == str)[1]
478478
this.permission.deny = perm.deny
479479
this.permission.allow = perm.allow
480480
this.options.name = SnowFlake.getSnowFlakeFromID(str, Role).getObject().name

‎webpage/style.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ small.subtext {
360360
vertical-align: top;
361361
overflow: auto;
362362
flex-shrink: 0;
363+
width: 56px;
363364
}
364365

365366
#servers {
@@ -1146,7 +1147,7 @@ span {
11461147
background: var(--profile-bg);
11471148
display: inline-block;
11481149
cursor: pointer;
1149-
box-shadow: 0 -.5in 1in color-mix(in srgb, var(--shadow) 42%, transparent);
1150+
box-shadow: 0 -.2in .8in color-mix(in srgb, var(--shadow) 60%, transparent);
11501151
width: 240px;
11511152
z-index: 3;
11521153
position: absolute;

‎webpage/user.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class User {
4747
this.bio = new MarkDown(userjson[thing], this.localuser)
4848
continue
4949
}
50-
if (thing === "id") {
50+
if (thing == "id") {
5151
this.snowflake = new SnowFlake(userjson[thing], this)
5252
continue
5353
}
@@ -98,7 +98,7 @@ class User {
9898
getpfpsrc() {
9999
if (this.hypotheticalpfp) return this.avatar
100100

101-
if (this.avatar === null) return instance.cdn + "/embed/avatars/3.png"
101+
if (this.avatar === null) return instance.cdn + "/embed/avatars/" + ((this.id >>> 22) % 6) + ".png?size=64"
102102
return instance.cdn + "/avatars/" + this.id + "/" + this.avatar + ".png?size=64"
103103
}
104104
buildprofile(x, y, type = "author") {

0 commit comments

Comments
 (0)
Please sign in to comment.