Lightingale Documentation
Welcome to the documentation hub of the Lightingale Community. See the sidebar for the list of documentations available.
To see a list of active projects not included here, feel free to visit the project website for the whole list, or GitHub pages host for projects hosted on GitHub.
Site powered by mdBook.
Clearnet CDNs are generously provided by Cloudflare, GCoreLabs, CloudFront, CacheFly and Fastly free of charge.
Services
For shorter descriptions, see Lightingale Services List.
- Lavender: Reddit-like Fediverse instance for the MLP fandom and LTGC.
- Liquestria: Invite-only semi-anarchy Minecraft survival multiplayer on mixnet.
- Matrix services: Managed Matrix bridges and more.
Projects
POSIX Shell
- Gel: ⛏ Rolling server bases, batteries included.
- Hyacinth: 💨 Build web projects with speed.
- Iceflakes: ❄️ Offline Linux installer images for everyone.
- Nightglow: 🌙 Yet another Cloudflare WARP client wrapper.
shx
: 📜 Bash/PDKSH shell action executor.- Stratus: ☕️ JavaScript runtime containers (Deno, Bun, Node.js).
Data sheets
midi-db
: 🎹 Data concerning MIDI standards.- Raven: 💨 Lightning-fast intuitive typing.
- SynPix: 👾 The open pixel font for embedded LCDs.
Rust
- Ensemble: 🎶 A synth framework in Rust.
Go
- Floaty: ☁️ Prevent Caddy loopbacks... Without traceability.
Java
- Mogician:
- Seperatist: 🔨 Seperated... As they should be.
Kotlin
JavaScript
- Berry: 🍇 Simple port exposure tunnel for stream entropy manipulation.
- Bread: 📦 Unified framework to stream binary in blocks.
- Crystal Quartz: 🎨 A colour palette generation system.
- Ditzy: 📬 Reconstruct stateful sockets over stateless messages.
- Eclipsed: 🔊 The Royal Canterlot Voice for SSE/
EventSource
.
- Ink Stone: 🖼 Modify font files with ease.
- Inkwell: 📒 The grand central terminal / Le grand terminal central.
- Leaflet: ⚠️ Stock Caddy error pages, free for anyone to use if kept credits.
- Lightfelt: 🕸 A collection of JS snippets for the Web and Deno.
- Mint: 🌱 Easy-to-configure load balancing serverless functions.
- Minuette: ⏳ Intercept, inspect, orchestrate.
- Octavia: 🎻 Event-driven multi-standard MIDI state-tracking library.
- Painted Palette: 🎨 Painting palettes, one pixel at a time.
- Parchment: 📃 Mark-down based client-side page generator.
- Rochelle: 🔪 Stream chunk splitting.
- Rosegap: 🌹🌙 Pleasant ads without compromises.
- Scope: 🔭 Easy-to-setup WireGuard meshing.
- Silk: 🕸 Bringing the fandom together.
- Snowy: ❄️ The
BroadcastChannel
polyfill for Firefox 29+ and Chrome 5+. - Track me, senpai!: 🍑 Just giving thanks to your visitor sharing their everything with you.
- Twinkle Sprinkle: 📜 Task wait signals and simple WAL.
- WingBlade: ☁️ One codebase, multiple runtimes.
Privacy policy
As of 6th Oct 2023, these terms are not yet in effect.
By using services provided by the Lightingale Community, you agree to the following terms.
Default
Unless stated explicitly otherwise, the following policy will be applied to any web-based service run by the Lightingale Community.
TL;DR, we have access to all of the data the client implementation chooses to share with us, but unless an error is caused or you explicitly want us to, none of the data would be stored.
Accessible
Below is the list of data accessible by us if provided, on the server-side without user interaction.
- When accessing via clearnet, the IP address of your exit.
- When accessing via clearnet, IP packet fingerprints. (e.g. TCP fingerprint, UDP fingerprint)
- TLS connection fingerprint, when connected via TLS.
- Standardized client-identifying headers, if provided. Visit MDN for more information. Below is a list of possible headers, and may not include all headers.
Accept
: Which types of content is accepted by the client.Accept-Encoding
: Encoding schemes accepted by the client, usually compression algorithms.Accept-Language
: Languages expected by the client.Authorization
: Tokens proving client's identification.Origin
: The URL of request's origin.Referer
: The initiator URL of each request.Sec-Fetch-Dest
: The initiator type of each request.Sec-Fetch-Mode
: Mode applied on requests.Sec-Fetch-Site
: Relationship between requested resource and source.User-Agent
: Implementation identification string provided by the client.X-Forwarded-For
,X-Real-IP
: If behind a reverse proxy, the connecting IP address observed by the reverse proxy. These headers are almost always stripped, spoofed or generalized on reverse proxies we have control of however.
- Client hints, sent by Chromium-based browsers (e.g. Google Chrome). Below is a list of headers sent unconditionally by Chromium-based browsers. To prevent us from receiving these headers, please switch to a browser that isn't based on Chromium.
Sec-CH-UA
: Array of implementation identification strings provided by the client.Sec-CH-UA-Mobile
: If the client runs on mobile platforms (e.g. Android, iOS).Sec-CH-UA-Platform
: The platform running the client, usually OS families.
- All other headers clients choose to provide.
- When the service involves server-side dynamically-generated content, basic cookies allowing said service to function properly.
We also have access to data you explicitly choose to share with us. They may be in cleartext or in their encrypted form.
Use
General
- Data explicitly stored by users will likely persist until takedowns.
- During suspected infiltrations, we will use any information accessible to identify and exterminate unauthorized access. Data stored during this period will be removed as soon as related investigations are finished.
- We do not share any information with any third-parties.
- Data requests from individuals and law enforcement agencies will be assessed before any action is taken. See the data request section for details.
Low-importance
Unless overriden, these uses do not store data.
- To deny access from clients we deem as unfit of service (WAF), we will use
Origin
,Referer
,Sec-CH-UA
,Sec-Fetch-Site
,User-Agent
, observed client IP address (if on clearnet/behind reverse proxies), IP packet fingerprints (if on clearnet) and TLS fingerprint. - To conserve bandwidth whenever we can, we will use
Accept-Encoding
. - To serve content to client's expectation, we will use
Accept
. - To distinguish between sessions if essential to the service client accesses,
Authorization
and/or basic cookies will be used. - To serve localized content in client's desired languages, we may use
Accept-Language
.
Medium-importance
Data stored from these uses will be kept for at most 7 days.
- Requests will be logged without observed IP addresses only upon causing non-critical software errors.
High-importance
Data stored from these uses will be kept for at most 365 days.
- Requests will be logged with observed IP addresses only upon causing critical software errors, or attempting to utilize known exploits.
Data access/removal request
- Approved data requests will be fulfilled within 30 days since approval, in the form that's available to us. Encrypted data will be provided as-is, along with their respective decryption keys only if available.
- Individuals can file requests for their data, and will be approved upon proving ownership.
- In most cases, individuals have power to remove data on their own.
- Law enforcement agencies can file requests for data. All data requests filed from law enforcement agencies will be made public.
- Requests sent from law enforcement agencies will only be approved if all listed criteria are satisfied.
- Belongs to a political body deemed as "full democracy" or "flawed democracy" by The Economist Democracy Index.
- Provides sufficient information for proving their identity.
- Belongs to the political body where related services are hosted, or can provide proof that affected users violated our acceptable usage policy.
- Affected resources of fulfilled removal requests from law enforcement agencies will be marked as
451 Resource Aflame
, along with the name of requested agency.
- Requests sent from law enforcement agencies will only be approved if all listed criteria are satisfied.
- If the service's ability to continue operation becomes next-to-impossible due to a failed compliance from a rejected data request, we will wipe all data stored on our behalf and cease operation on said service. The same goes for the Lightingale Community itself.
Infrastructure providers
We extensively rely on Cloudflare for our infrastructure on the clearnet. If you do not want to go through Cloudflare, feel free to access our services through alternative means. Otherwise, a copy of privacy policy from Cloudflare could be obtained.
To improve availability and/or decrease cost on some of our services, we may also use other infrastructure providers. Check their respective privacy policies for details. Below is a list of providers we rely on.
- AWS CloudFront, for CDN.
- Anonymized/generalized data generated by AWS CloudFront are stored for 30 days by the provider.
- AWS Lambda, for serverless computing.
- Anonymized/generalized data generated by AWS Lambda are stored for 30 days by the provider.
- CacheFly, for CDN.
- Data generated by CacheFly are never stored.
- Cloudflare, for DNS, CDN, WAF and edge serverless computing.
- Identifying data generated by Cloudflare are stored for 24 hours by the provider.
- Anonymized/generalized data generated by Cloudflare are stored for 30 days by the provider.
- Deno Deploy, for edge serverless computing.
- Anonymized/generalized data generated by Deno Deploy are stored for 30 days by the provider.
- Fastly, for CDN and edge serverless computing.
- Data generated by Fastly are never stored.
- GCoreLabs, for CDN.
- Anonymized/generalized data generated by GCoreLabs are stored for 30 days by the provider.
Access denial
VPN
If you're accessing any Lightingale service from a VPN, chances are you're already blocked by us, but will get unblocked if with mixnets like Tor, or encrypted proxies. This is intentional.
We strongly support privacy and anonimity, while also highly detest the idea of fattening any commercial VPN vendor. VPNs do not offer privacy or security on the Internet in any way, let alone either anonimity or anti-censorship, and in no way any of them contribute to the effort of developing either anti-censorship or concealing technology to truly liberate the masses. As such, we've long since decided to take direct action, actively identifying and fingerprinting VPNs, while advising people to switch to real solutions instead.
Client
We identify some client programs as high-risk, and block requests from those programs if identified.
FAQ
I'm using a VPN, what should I do?
To put it simply, please stop using a VPN to access us.
If you're familiar with accessing services hosted on mixnets, you can access our services via alternative means. Or if you don't want to go through the hassle, please disconnect from your VPN, and if you have access to either exit/outproxy-enabled mixnet (e.g. Tor, I2P (I2Pd is recommended if you are comfortable with command line), Lokinet) or encrypted proxies, use them instead.
What if I'm blocked wrongly?
Within 18 hours, please contact us and provide your Cloudflare Ray ID in your unblocking appeal. After we've verified that you did indeed not connect from a VPN, you'll be unblocked as soon as possible. However, if you used a client program we deem as high-risk, we will reject your appeal immediately.
Could you stop blocking VPNs?
No.
Acceptable Usage Policy
These terms do not yet have legal liabilities, however they are enforced.
Underlined terms should have definitions available in the Definitions section.
Definitions
- Child pornography: Depictions of underage humans or underage characters resembling humans.
- Underage: Below 18 years old.
Disallowed use
AUP does not cover cases where reasons of policy enforcements are explained.
- Reselling any of our public services, which is free-of-charge for all.
- Breaching the awareness scope defined by projects/services.
- Scanning us or to scan others (e.g. port scanning).
- Gaining unauthorized resource access.
- Degrading the performance of our servers (e.g. flooding).
- Violating others privacy (e.g. doxxing).
- Impersonating existing identities without stating satire status.
- Exploiting stolen identities.
- Distributing unsolicited data (e.g. spam).
- Scamming.
- Hate speech (e.g. racism, xenophobia).
- Promotion of self-harm (e.g. suicide).
- Harming others physically or psychologicaly (e.g. torture threats, death threats, harassement).
- Engaging in distribution of illegal substances, human organs, guns and etc.
- Promoting, encouraging and/or beautifying any of the following topics.
- Crimes against humanity (e.g. massacre).
- Terrorism, its practices and exercising organizations.
- Distributing content matching any of the following criteria, without explicit warning to the target audience.
- Malware.
- Phishing content.
- Pornography.
- Distributing and storing content matching any of the following criteria.
- Child pornography.
- Pornography without consent of involved parties.
- Defaming us without any validated proof.
Terms of Service
This agreement will become legally binding once Lightingale Community becomes a legally-registered non-profit organization.
As of 6th Oct 2023, these terms are not yet in effect.
In this agreement...
- The term "you" or "your" refer to "the user".
- The term "we", "us" or "our" refer to Lightingale Community itself and its members.
- The term "service" or "services" refer to publicly-available listed services hosted on behalf of Lightingale Community. The list is available here.
By accessing content or using the services provided by the Lightingale Community, you agree to the following terms. Specific services will apply amendments to fit their specific needs.
Any material changes to these terms will be publicly notified via our Mastodon and our Telegram channel at least 7 days prior. If you wish to exercise your right to reject such changes, you can file complaints to us, or stop using the service altogether.
Disclaimer
-
We reserve the right to modify the service, including but not limited to changing certain features and updating the related software.
-
We reserve the right to terminate your access to some or all of our services.
-
We may deny access to certain services based on the geographic location of your immediate connection.
-
We will attempt to prevent disruptions, defects and losses of data in our offered services, but despite our best efforts, we do not and can not guarantee availability of all times, and we are not responsible for materials served by us. Our service comes with absolutely no warranty, to the extent permitted by applicable law. You are solely responsible for your use of service.
The service
This section is defined in different services we offer to the public.
Software
Lightingale Community is powered fully by and produces FOSS, fit under the definition set by the Free Software Foundation. Further acknowledgements may be made in README files when we use software projects that require them.
Our content
Except for software, unless stated otherwise explicitly, content belongs to us is licensed under CC BY-NC-SA 4.0 License. Our members hold the rights of content they produced.
Your content
This section applies to services offering UGC.
You hold the rights to your own content, but you give us a license when submitting your content to us. Upon submission, you permit us to do the following to your submitted content. These terms are world-wide, non-exclusive, royalty-free, transferrable and perpetual.
- To store and display your content, you permit us to use, copy, store, distribute your content in ways consistent with your use of the services.
- To adapt your content for use of different platforms by different users with various backgrounds, you permit us to monitor, modify, translate and reformat your content.
- For public availability, you permit us to publish, publicly perform, or publicly display your content, if you've chosen to make it visible to others.
- To allow our services to work as intended, you permit us to sublicense your content.
We reserve the right to block, remove or wipe your content if in breach with these terms or other terms in effect.
Acceptable usage
As a user of services offered by us, you agree to adhere to our acceptable usage policy. Violations of AUP will result in a termination, and may result in your data made available to law enforcement agencies.
We encourage you to report abuses of our services with proof. We accept reports made via email at abuse (at) ltgc (dot) cc
.
Donation
This section is subject to changes as our legal status changes.
We are not responsible for fulfilling any additional requirement attached to the donations made to us.
Applicable law
This section is subject to change as our legal status changes.
Legal contact
This section is subject to change as our legal status changes.
Legal contacts may be filed via email to legal (at) ltgc (dot) cc
. We do not have a physical location available.
UGC Availability
To prevent Lightingale Community from getting blocked as a whole in certain countries, we've been forced to restrict or deny direct access from those countries. A restricted service coverage would've been marginally better than nothing at all.
We offer two levels of UGC services: high-liberty and restricted. Levels are separated by the measures avalable to the users, and users' ability to freely express whatever they desire. Some countries may have been denied direct access from high-liberty UGC services, but not restricted ones.
If you've been redirected to this page, it's likely that you have been denied direct access to our UGC service, and we have no other choice but to offer our deepest apology.
List of countries affected
Denied from high-liberty and restricted UGC services
AE
: United Arab EmiratesAF
: AfghanistanAZ
: AzerbaijanBD
: BangladeshBH
: BahrainBT
: BhutanBY
: BelarusCN
: ChinaCU
: CubaDJ
: DjiboutiDZ
: AlgeriaEG
: EgyptER
: EritreaET
: EthiopiaGT
: GuatemalaHN
: HondurasKH
: CambodiaKZ
: KazakhstanIL
: IsraelIN
: IndiaIQ
: IraqIR
: IranLA
: LaosLB
: LebanonLY
: LibyaMM
: MyanmarNI
: NicaraguaNK
(KP
): North KoreaOM
: OmanPK
: PakistanPS
: PalestineRU
: RussiaRW
: RwandaSA
: Saudi ArabiaSD
: SudanSL
: Sri LankaSO
: SomaliaSY
: SyriaTJ
: TajikstanTM
: TurkmenistanTR
: TurkeyUZ
: UzbekistanVE
: VenezuelaVN
: VietnamYE
: Yemen
Denied from high-liberty UGC services
BO
: BoliviaCD
: Democratic Republic of CongoCM
: CameroonGQ
: Equatorial GuineaHK
: Hong KongKG
: KyrgyzstanJO
: JordanKW
: KuwaitLS
: LesothoMA
: MoroccoMX
: MexicoPE
: PeruPH
: PhilippinesSG
: SingaporeSS
: South SudanSV
: El SalvadorUG
: Uganda
Technologies
Preferred technologies
Languages and runtimes
Networking
Operating systems
Virtualization and containerization
Miscellaneous
Used technologies
Technologies listed here may have been used by some of our projects. None of the technologies listed below are a preference, though project can freely choose to use them.
Languages and runtimes
Virtualization and containerization
Miscellaneous
Avoided technologies
Technologies listed here will have their usage be discouraged and avoided. However, projects can still develop for them only if necessary. Software already developed with these technologies can also be deployed.
Languages and runtimes
Operating systems
Miscellaneous
Banned technologies
Usage of technologies listed here are entirely banned within LTGC. Bans do not extend to members themselves.
Frameworks
Virtualization and containerization
Miscellaneous
Content encoding
None of the encodings listed are involved with patent concerns.
Usage | Encoding | Extension |
---|---|---|
Rasterized image | JPEG XL | .jxl |
JPEG | .jpg |
|
WebP | .webp |
|
AVIF | .avif |
|
Vector image | SVG | .svg |
Lossy audio | Opus | .opus |
Vorbis | .ogg |
|
AAC-LC | .m4a .aac |
|
Lossless audio | WavPack | .wv |
FLAC | .flac |
|
Web compression | Zstd | .zst |
Brotli | .br |
|
gzip | .gz |
|
Bundle compression | lzip | .lz .tlz |
bzip2 | .bz2 .tbz2 |
|
xz | .xz .txz |
|
Font | WOFF2 | .woff2 |
Read below for further details.
Rasterized image encoding
Lossy still
As WebP is properly supported in every browser built for systems newer than Windows XP, and it offers better quality-to-size ratio than all JPEG encoders, it is considered the best fallback format. However, as JPEG XL exists as an all-around better universal image format, lossy images should also be encoded with JPEG XL whenever possible.
Compared to all other image formats, JPEG XL offers jawdropping image fidelity, unmatched quality-to-size ratio, proper progressive loading and better responsiveness. The cherry on top of JPEG XL would be its ability to losslessly transcode from existing JPEG files, offering about 20% size reduction with cheap JPEG lossless bitstream reconstruction, which paves its way to be a backwards-compatible drop-in replacement for image storage and distribution.
Things to take notice of:
- mozJPEG-fronted JPEG, while offering a good choice for backwards-compatibility, shouldn't be used unless necessary when size is a consideration. mozJPEG is generally superseded by
jpegli
. - AVIF offers an advantage on size, when progressive support, boundary artifacts and codec performance (slower than all others multiple times) aren't in consideration.
- AVIF is observed to have fewer observable artifacts for images with a simpler shading.
- The reference AVIF settings provide a balancing point between JXL
-d 1
and JXL-d 2
. jpegli
for JPEG from the JPEG XL team provides a reasonable front for backwards-compatible JPEG XL encoding. The estimated file size on fronted JPEG XL files are around 82.5% of the original JPEG files.
Explanations of image encoding uses:
- Delivery: Size-first with generally-acceptable quality.
- Delivery+: Balance between size and quality.
- Near-lossless: Shaving as much size as possible, while still being mostly indistinguishable, even when zoomed in at 200%.
Uses | SSIMULACRA2 | Butteraugli | DSSIM |
---|---|---|---|
Delivery | 80 | 2.0 | 0.0008 |
Delivery+ | 85 | 1.0 | 0.0004 |
Near-lossless | 90+ | 0.4- | 0.0001- |
The size ratio values listed below approach expectations on a large scale, based on experiments conducted on a relatively large scale with non-photographic images modelling 15.6% lossy inputs. Lossless inputs induce better (smaller) expectations, while lossy inputs tip the balance in reverse. Photograpic images will generally have a better (smaller) ratio than non-photographic images, but individual images may still yield greatly varied results.
Codec | Use | Params | Ratio |
---|---|---|---|
JPEG XL | Delivery (quality) | cjxl -j 0 -d 2 -e 7 -p --progressive_dc 1 |
8.52% |
Delivery (speed) | cjxl -j 0 -d 2 -e 4 -p --progressive_dc 1 |
- | |
Delivery+ | cjxl -j 0 -d 1 -e 7 -p --progressive_dc 1 |
14% | |
Near-lossless | cjxl -j 0 -m 1 -d 0.2 -e 7 |
32.6% | |
WebP | Delivery (quality) | cwebp -m 5 -psnr 56 -qrange 90 99 |
21.2% |
Delivery (speed) | cwebp -m 5 -q 95 |
16.8% | |
Delivery+ | cwebp -m 5 -q 99 |
- | |
Near-lossless | cwebp -near_lossless 60 |
62.3% | |
JPEG | Delivery | cjpegli -d 1 -p 2 |
16.8% |
AVIF | Delivery | [effort=4,lossless=false,Q=90] |
15.7% |
The full feature set comparison chart is available on Cloudinary.
Lossless still
JPEG XL lossless and WebP lossless are mostly on par, either could be the better solution at times. For compatibility reasons, WebP lossless should always be offered, while JPEG XL lossless could be offered only when the resulting file is smaller than that of WebP lossless. AVIF lossless is currently consistently worse than either JPEG XL or WebP, as such it's not recommended at all.
Do not enable progressive encoding for JPEG XL lossless, or the resulting file will be several times bigger than PNG files.
Codec | Parameters | Ratio |
---|---|---|
JPEG XL | cjxl -j 0 -d 0 -e 7 | 70.2% |
WebP | cwebp -m 6 -lossless | 78.1% |
Lossy animated
Lossy animated WebP is the current baseline for animated image sequences, while lossy animated AVIF offers the best quality against others by a wide margin. Lossy animated JPEG XL doesn't offer a significant advantage against WebP, and is currently beaten by AVIF.
Audio encoding
Lossy
When high sampling rates are required, choose Vorbis. When support for the Apple ecosystem is required, choose AAC-LC. Otherwise use Opus under all possible scenarios, but beware that Opus only supports sampling at 48kHz.
Below are the suggested bitrates under different scenarios, when encoding stereo audio content under either 44.1kHz or 48kHz. Audio content should be encoded with constrained variable bitrate (CVBR).
The AAC-LC encoder in question is libfdk_aac
, being the best FOSS AAC-LC encoder out there. The only AAC-LC encoder better than libfdk_aac
is Apple's Audio Toolbox, which is proprietary and not in consideration.
Codec | Basic | Stream | Balanced | Generic | Quality |
---|---|---|---|---|---|
Opus | 96kbps | 144kbps | 160kbps | 192kbps | 256kbps |
Vorbis | 128kbps | 160kbps | 192kbps | 224kbps | 320kbps |
AAC-LC | 128kbps | 160kbps | 192kbps | 224kbps | 320kbps |
Keep in mind that the scenario under "basic" indicates that, all audio content encoded with provided parameters should be virtually indistinguishable from LAME-encoded MP3 files at 192kbps.
Lossless
Streaming lossless audio is generally considered a bad idea due to high bandwidth usage. It's generally more useful for archival purposes.
You should choose FLAC when...
- Browser support is needed.
- The target is severely underpowered.
- The target only supports FLAC for lossless audio compression.
You should choose WavPack when...
- You need a smaller file.
- Higher bit depth is needed (more than 24).
Codec | Parameters |
---|---|
WavPack | wavpack -hhvx -x 3 |
FLAC | flac -V8 -e --no-padding -f |
Additional considerations:
- If you do not intend to distribute high bit-depth lossless audio, but the input you have is of high bit-depth, you can re-sample it to somewhere between 16-bit (-96 dB) and 24-bit (-144 dB). Use
--pre-quantize=16
for WavPack.
Compression
Web
Brotli should be preferred over gzip
at all times. Static low-entropy content (e.g. plain text files) should always be pre-compressed, with or without the original uncompressed file available. For dynamic content compression, zstd
at level 8 consumes significantly less than the resources used for Brotli, all the while outperforming Brotli in terms of output size.
For static precompression, the original file can be omitted when the space is constrained, serving only precompressed blobs. When compatibility with other infrastructure isn't in consideration, precompressed gzip
files can also be omitted, although it's not recommended in most cases. zstd
isn't suitable for static precompression, as even at compression level 22 it falls behind Brotli at its highest compression level. However, a recommendation is still available for reasonable reference. Zopfli is an alternative compressor for gzip
, which --i1
outperforms gzip
even at level 9, however only --i1
and --i2
are recommeded for general use.
The table below provides a quick reference of levels and estimated size reduction by use case.
Algorithm | Use | Params | Reduction Ratio |
---|---|---|---|
Brotli | Dynamic | brotli -4 |
69.64% |
Static | brotli -q 11 |
73.41% | |
Zstd | Dynamic | zstd -7 |
69.82% |
Static (not recommended) |
zstd -19 |
72.92% | |
gzip | Dynamic | gzip -4 |
66.48% |
Static | zopfli --i1 |
68.08% |
On a case-by-case basis, Compression Tester could be used to see algorithms in action. For a more comprehensive comparison, Morotti's Compression Results could be used.
Bundle
lzip
is the de-facto standard of bundle compression, featuring good compression ratio with data recovery abilities. Quality should always set to 9
, unless a lower quality value is proven to yield a better result for smaller files, or time constraints are set.
bzip2
or xz
should only be considered for compatibility purposes.
Font
As practically all modern browsers support the WOFF2 font format, all required TrueType and OpenType fonts must be served as WOFF2 files instead. If for unspecified reasons that original files must be served, always consider precompression and avoid storing uncompressed files.
Region and DC codes
Datacentre codes
DC Code | Country | Location | Native Form |
---|---|---|---|
VIE | AT | Vienna | Wien |
MEL | AU | Melbourne, Victoria | |
SYD | AU | Sydney, New South Wales | |
ANR | BE | Antwerp, Flanders | Anvers, Flamande / Antwerpen, Vlaanderen |
GHI | BE | Saint-Ghislain, Hainaut, Wallonia | Saint-Guilagne, Hénau, Walonnie |
SOF | BG | Sofia | София |
TOR | CA | Toronto, Ontario | |
YBN | CA | Beauharnois, Quebec | Beauharnois, Québec |
YHZ | CA | Halifax, Nova Scotia | |
YUL | CA | Montreal, Quebec | Montréal, Québec |
YVR | CA | Vancouver, British Colombia | |
YWG | CA | Winnipeg, Manitoba | |
YYC | CA | Calgary, Alberta | |
GVA | CH | Geneva | Genève |
ZRH | CH | Zurich | Zürich |
DUS | DE | Dusseldorf, North Rhine-Westphalia | Düsseldorf, Nordrhein-Westfalen |
FAL | DE | Falkenstein, Bavaria | Falkenstein, Bayern |
FRA | DE | Frankfurt, Hesse | Frankfurt, Hessen |
LBG | DE | Limburg, Hesse | Limburg an der Lahn, Hessen |
MUC | DE | Munich, Bavaria | München, Bayern |
NUE | DE | Nuremberg, Bavaria | Nürnberg, Bayern |
BCN | ES | Barcelona, Catalonia | Barcelona, Cataluña |
MAD | ES | Madrid | |
HEL | FI | Helsinki, Uusimaa | Helsinki, Uudenmann |
HMX | FI | Hamina, Kotka-Hamina, Kymenlaakso | |
GVS | FR | Gravelines, Dunkirk, Nord, Hauts-de-France | Gravelines, Dunkerque, Nord, Hauts-de-France |
LIL | FR | Lille, Nord, Hauts-de-France | |
MRS | FR | Marseille, Bouches-du-Rhône, Provence-Alpes-Côte d'Azur | |
PAR | FR | Paris, Île-de-France | |
RBX | FR | Roubaix, Nord, Hauts-de-France | |
SXB | FR | Strasbourg, Bas-Rhin, Grand Est | |
BHX | GB | Birmingham, West Midlands, England | |
CVT | GB | Coventry, West Midlands, England | |
CWL | GB | Cardiff, South Glamorgan, Wales | Caerdydd, De Morgannwg, Cymru |
LON | GB | London, Greater London, England | |
MAN | GB | Manchester, Greater Manchester, England | |
MDH | GB | Maidenhead, Berkshire, England | |
NWP | GB | Newport, Gwent, Wales | Casnewydd, Gwent, Cymru |
PSM | GB | Portsmouth, Hampshire, England | |
RDT | GB | Redditch, Worcestershire, England | |
HKG | HK | Hong Kong | 香港 |
HKW | HK | Tsuen Wan, Tsuen Wan, New Territories | 新界荃灣區荃灣 |
HTK | HK | Tseung Kwan O, Sai Kung, New Territories | 新界西貢區將軍澳 |
BUD | HU | Budapest | |
JKT | ID | Jarkata, Java, Indonesia | |
DUB | IE | Dublin, Leinster | Baile Átha Cliath, Cúige Laighean |
MIL | IT | Milan, Lombardy | Milano, Lombardia |
ROM | IT | Rome, Lazio | Roma, Lazio |
TRN | IT | Turin, Piedmont | Turin, Piemont / Torino, Piemonte |
INZ | JP | Inzai, Chiba | 千葉県印西市 |
OSK | JP | Ōsaka | 大阪府 |
TYO | JP | Tökyö | 東京都 |
CCN | KO | Chuncheon, Gangwon | 江原特別自治道春川市 |
ICN | KO | Incheon | 仁川廣域市 |
SOL | KO | Seoul | 서울特別市 |
LUX | LU | Luxembourg | Lëtzebuerg |
KIV | MD | Chisinau | Chișinău |
KUL | MY | Kuala Lumpur | |
AMS | NL | Amsterdam, North Holland | Amsterdam, Noord-Holland |
DRT | NL | Dronten, Flevoland | |
EEM | NL | Eemshaven, Het Hogeland, Groningen | |
HAG | NL | The Hague, South Holland | Den Haag, Zuid-Holland |
HRL | NL | Haarlem, North Holland | Haarlem, Noord-Holland |
MPL | NL | Meppel, Drenthe | |
NLW | NL | Naaldwijk, South Holland | Naaldwijk, Zuid-Holland |
RTM | NL | Rotterdam, South Holland | Rotterdam, Zuid-Holland |
WMR | NL | Wormer, North Holland | Wormer, Noord-Hooland |
OSL | NO | Oslo | |
TRF | NO | Sandefjord, Vestfold og Telemark | |
GDN | PO | Gdansk, Pomeranian | Gdańsk, Pomorskie |
WAW | PO | Warsaw, Masovian | Warszawa, Mazowieckie |
LIS | PT | Lisbon | Lisboa |
EKT | RU | Yekaterinburg, Sverdlovsk | Екатеринбург, Свердловская область |
KHV | RU | Khabarovsk, Khabarovsk Krai | Хабаровск, Хабаровский край |
KZN | RU | Kazan, Tatarstan | Казань, Татарстан |
MOW | RU | Moscow | Москва |
OVB | RU | Novosibirsk, Novosibirsk Oblast | Новосибирск, Новосибирская область |
SPT | RU | Saint Petersburg | Санкт-Петербург |
VVO | RU | Vladivostok, Primorsky Krai | Владивосток, Приморский край |
STO | SE | Stockholm | |
TNP | SE | Tjoernarp, Scania | Tjörnarp, Skåne |
SGP | SG | Singapore | |
SGG | SG | Jurong West, West Region | 西區裕廊西 |
SGS | SG | Simei, Tampine, East Region | 東區淡賓尼四美 |
IST | TR | Istanbul, Marmara | İstanbul, Marmara Bölgesi |
CHW | TW | Changhua County | 彰化縣 |
TPE | TW | Taipei City | 臺北市 |
DNK | UA | Dnipro, Dnipropetrovsk Oblast | Дніпро, Дніпропетровська область |
HRK | UA | Kharkiv, Kharkiv Oblast | Харків, Харківська область |
IEV | UA | Kyiv | Київ |
ASH | US | Ashburn, Virginia | |
ATL | US | Atlanta, Georgia | |
BUF | US | Buffalo, New York | |
CBL | US | Council Bluffs, Iowa | |
CHI | US | Chicago, Illinois | |
CLB | US | Colombus, Ohio | |
DAL | US | Dallas, Texas | |
DEN | US | Denver, Colorado | |
DLS | US | The Dalles, Wasco County, Oregon | |
EWR | US | Newark, New York | |
FET | US | Fremont, California | |
FQC | US | (Vint Hill,) Fauquier County, Virginia | |
HIO | US | Hillsboro, Portland, Oregon | |
HON | US | Honolulu, Hawaii | Honolulu, Hawaiʻi |
HST | US | Houston, Texas | |
JAX | US | Jacksonville, Florida | |
LAS | US | Las Vegas, Nevada | |
LAX | US | Los Angeles, California | |
MIA | US | Miami, Florida | |
MSP | US | Minneapolis, Minnesota | |
NYC | US | New York City, New York | |
PHX | US | Phoenix, Arizona | |
POR | US | Portland, Oregon | |
SCC | US | Secaucus, New Jersey | |
SEA | US | Seattle, Washington | |
SFO | US | San Francisco, California | |
SJC | US | San Jose, California | |
SLC | US | Salt Lake City, Utah | |
SNU | US | Santa Clara, California | |
STL | US | St. Louis, Missouri | |
TPA | US | Tampa, Florida | |
USB | US | Moncks Corner, South Carolina |
Versioning
Semantic versioning
Visit semver.org for more information.
Decaday versioning
Inspired by Minecraft's snapshot versioning appraoch, decaday versioning is used for projects releasing snapshots, where the versioning follows the YYYYdDDx
, where YYYY
denotes the full year, d
can either be d
or m
in different projects (due to historical mistakes...), DD
denotes the decaday of the year, and x
denotes the ever-increasing alphabetical index of snapshot versions.
"Decaday" is a way of dividing months to three roughly equal portions, where it usually tries to group 10 days as a "decaday". In a typical month, the 1st to the 10th day belongs to the first decaday, the 11th to the 20th belongs to the second, and the 21st to the 30th belongs to the third. If a month has 31 days, the 31st day belongs to the third decaday. This approach avoids the problem of different choices in a week's starting point.
Take 2023d30b
as an example. 2023
means the snapshot was released in 2023, 30
means the snapshot was released between 21st October and 31st October, and b
indicates the version was released as the second snapshot between the time period.
Project origins
What led to LTGC projects?
- Thestral: "Is oblivious user authentication possible?"
- Nightglow: "Ugh the official Cloudflare WARP client is so crappy and I don't need that much functionality anyways!"
- Scope: "No existing meshed WireGuard orchestration fits our needs!"
- Octavia: "Can I make a better MIDI visualizer?"
shx
: "I hate Node.js but I need something likenpx
."- SynPix: "Emulated screens bundled in Octavia need a libre bitmap font."
- MIDI DB: "Why isn't there readily-available multi-standard MIDI data sheet?"
- Hyacinth: "JS projects should be built faster!"
- Painted Palette: "What if I made a better headless bot?"
- WingBlade: "Can I make the same codebase run everywhere?"
- (unnamed): "Let's build a clean, lightweight and ad-free boardgame experience!"
- Linen: "Wanna run an r/place replica of our own?"
- Cubics: "Want a convenient diagram generator for Rubik's cube-like puzzles..."
- Raven: "I don't want to relearn a keyboard layout to type in another writing system."
- (unnamed): "Wanna optimize Minecraft?"
- Rosegap: "Daily Dose of Pony needs an ad system."
- Ink Stone: "Will SynPix ever be released as font files?"
Where did names of projects come from?
Author | Work | Project | Notes |
Bucking Nonsense | Cooking Roach | Rochelle | |
Dee Pad | A Wolf in Sheep's Clothing | Daily Scoop | |
drFraud | Accepting Change | Patchwork | |
ItchyStomach | Shed My Skin | Mint | Mint Flower (Split Horizon) |
Jigsaw | Cambiare | Octavia Cambiare | |
Lauren Faust | My Little Pony: Friendship is Magic | Berry | Berry Punch |
Ditzy | Ditzy Doo (Derpy Hooves) | ||
Eclipsed | S02E04, Luna Eclipsed | ||
Flitter | |||
Heartstrings | Lyra Heartstrings | ||
Inkwell | Raven Inkwell | ||
Minuette | |||
Octavia | |||
Raven | Raven Inkwell | ||
Rosegap | Roseluck | ||
Twinkle Sprinkles | Twilight Sparkle | ||
Random_User | A Swift Message | Graceful Lattice | |
Ink Stone | |||
Swift Message | |||
Starscribe | Fine Print | Rosegap | Spark Gap (Tracy, or "Tracing") |
Thadius0 | Shifting Melodies | Painted Palette | |
Scope | Scope Lens | ||
WingBlade | Midnight Song's wing blade | ||
Wanderer D | The Three Sisters | Acari |
Project inspiration hiearchy
- Project Moonlight (Media)
- Heartstrings
- Octavia
- Cambiare
- Ensemble
- Hyacinth
shx
- MIDI DB
- Snowy
- Swiftbook
- SynPix
- Ink Stone
- Project Lilac (Translation, localization and linguistics)
- Noitieng
- Raven
- Project Weaving (Networking and isolation)
- Floaty
- Nightglow
- Patchwork
- Scope
- Uncategorized
- Acari
- Berry
- Bread
- Citrus
- Crystal Quartz
- Daily Scoop
- Ditzy
- Domain DB
- Flex
- Flitter
- Graceful Lattice
- Inkwell
- Leaflet
- LiteBlock
- Mint
- Flame
- Minuette
- Painted Palette
- WingBlade
- Eclipsed
- Rochelle
- Stratus
- Twinkle Sprinkles
- WingBlade
- Patchwork
- PonyTrails
- Gel
- Iceflakes
- Gel
- Rosegap
- Seperatist
- Silk
- Thestral
List of technologies
JavaScript
Engines
Name | Conformance level |
---|---|
V8 | 8 |
LibJS | 8 |
JavaScriptCore | 8 |
SpiderMonkey | 8 |
GraalJS | 8 |
QuickJS | 8 |
Kiesel | 4 |
Rhino | 4 |
Porffor | 2 |
Nova | 2 |
Boa | 0 |
Duktape | 0 |
lo | 0 |
Runtimes
Name | Engine | Node/NPM |
---|---|---|
Deno | V8 | Manual |
Dune | V8 | Yes |
Node.js | V8 | Yes |
workerd | V8 | No |
Bun | JavaScriptCore | Yes |
Spiderfire | SpiderMonkey | No |
WinterJS | SpiderMonkey | No |
Bare | QuickJS | No |
Javy | QuickJS | No |
LLRT | QuickJS | No |
txiki.js | QuickJS | No |
List of sizes of data types
Numbers
Integers
Go | Rust/Zig | Java | Scala | Kotlin | C# | C |
---|---|---|---|---|---|---|
bool | bool | boolean | Boolean | Boolean | bool | bool |
int8 | i8 | byte | Byte | Byte | sbyte | signed char |
int16 | i16 | short | Short | Short | short | (signed ) short |
int32 | i32 | int | Int | Int | int | (signed ) long |
int64 | i64 | long | Long | Long | long | (signed ) long long |
- | i128 | - | - | - | - | - |
int | isize | - | - | - | nint | - |
uint8 | u8 | - | - | UByte | byte | unsigned char |
uint16 | u16 | char | Char | UShort | ushort | unsighed short |
uint32 | u32 | - | - | UInt | uint | unsigned long |
uint64 | u64 | - | - | ULong | ulong | unsigned long long |
- | u128 | - | - | - | - | - |
uint | usize | - | - | - | nuint | - |
uintptr | - | - | - | - | - | - |
- Aliases for certain integer types:
u8
:byte
(Go)i32
:rune
(Go)bool
:_Bool
(C)
- GNU
libc
offers alternative types for intergers. Read more
Floats and more
Go | Rust/Zig | Java | Scala/Kotlin | C# | C |
---|---|---|---|---|---|
- | f16 | - | - | - | - |
float32 | f32 | float | Float | float | float |
float64 | f64 | double | Double | double | double |
- | f128 | - | - | - | __float128 |
complex64 | - | - | - | - | float _Complex |
complex128 | - | - | - | - | double _Complex |
- The C#
decimal
type occupies 128 bits, but is different fromf128
. long double
in C varies in compiler implementations.- Some C implementations may use
_Float128
forf128
.
Lavender
Lavender is a friendly discussion lounge for both the My Little Pony fandom and LTGC, powered by the magic of Lemmy. No matter what you are, be a pony, dragon, hippogriff or draconnequus, you're welcome here!
Lavender adheres to the general Terms of Service and Acceptable Usage Policy.
The incubator thread can be viewed here.
Access
Addresses
The service can be accessed from the addresses listed below.
- Clearnet (not recommended): lavender.ltgc.cc
- Tor: lavender...j33btaqd.onion
- I2P (I2Pd): lavender.ltgc.i2p or lavender...v6bg4rfa.b32.i2p
- Lokinet: mwt5jdqg...jpxctyeo.loki
- Yggdrasil: lav.ygg.ltgc.cc
Panels
Read Lavender panels.
Account registration
Alpha phase
Lavender is still in the alpha phase. During the alpha phase...
- Only people already having a presence on Fediverse can apply for account registration. You must fulfill any criteria listed below.
- Have an account on one of the listed public instances for more than 14 days, with at least 7 posts in total.
- Have an account on any public Fediverse instances for more than 14 days, with at least 7 posts in total, and the identity relates to the My Little Pony fandom.
- Be a member of the Lightingale Community.
Moderation
Alpha phase
Lavender is still in the alpha phase. During the alpha phase...
- Only accounts on the instance itself can apply to become a moderator.
- Only with two or more
Lavender Panels
Lavender currently organizes the following panels.
Best of Fedi Pones
Artists new to the Fediverse often complain about not reaching enough audiences. So what's the solution? Well, with a weekly panel promoting pony artworks published on the Fediverse, of course!
Organized by a group of Fediverse enthusiasts from the My Little Pony fandom, Best of Fedi Pones seeks to bring what the Fediverse has to offer to everyone enjoying the creativity from the pony fandom. Better together!
Source code: Codeberg
Artwork submission
Submitting artworks will get them included in the issues of Best of Fedi Pones if not denied. All submitted artworks, unless violating AUP, will be also referenced by the MLP English Lavender community.
Submitting artworks
Best of Fedi Pones has been directly integrated into the Fediverse since issue 10. Submission only requires the inclusion of #weeklypony
tag while also mentioning @[email protected]
. Works both when posting yourself and replying to others.
Inclusion denial
Submissions will be denied if they match at least one of criteria listed below.
- Is not SFW.
- Is generated by neural networks. Inspired by or assisted with NN doesn't count.
- Not posted by the artist themself.
- Violates LTGC AUP.
- Was posted for longer than 14 days to the deadline of the target issue.
Voting and issuing
Voting of each submission is done in a room accessible to all panel organizers. While the room is bridged to Discord and Telegram, only votes from Matrix and Discord are counted due to technical limitations.
Each eligible voter can part one ⭐️(:star:
) emoji to give a submission an upvote. Submissions with high vote count will be ordered first, and submissions sharing the same vote count have their exact order determined by the hash of the origin URL. No downvotes are available.
Voting of each issue generally begins at 12:00 UTC +0 on every Saturday, and ends at 18:00 UTC +0 on the next day. The dataset should be available shortly after the voting ends, and any organizer can release the issue with the dataset.
To prevent accusations of theft, except for the cover art, all submission images must be hotlinked from source. Cover art is generally selected among the submission with the top 60% vote count, entirely by the organizer posting the issue with their own preferences. However, it's advised to avoid featuring the same artist within the span of 9 issues, and artists new to the Fediverse are advised to be preferred.
IM services
Lightingale Community has been hosting messaging services like Matrix for ease of communication, ever since the community's early days in 2021.
Services
Matrix
We run a Synapse homeserver for hosting all of our bridges and for internal communication. Only members of the Lightingale Community can apply for accounts on the homeserver.
Mumble
Planned. Internal and mixnet access only, with no clearnet access planned.
XMPP
We run a Prosody server with native mixnet access, for easier interfacing with the federated XMPP ecosystem. It is not intended for primary use, and its service availability is generally worse than Matrix.
Bridges
As long as adhereing to the Acceptable Usage Policy, members on our homeserver can freely use any of the bridges we host. Certain bridges offer integration to mixnets and overlay networks, namely I2P, Tor and Yggdrasil.
However, please note that integrations with alternative DNS systems (e.g. OpenNIC, ALFIS) likely will not work.
Group chat bridges
The following bridges support both group chats and direct messages.
- Discord to Matrix (via mautrix-discord)
- IRC to Matrix (via Heisenbridge) (planned)
- Mumble to Matrix (via MandM-bridge) (planned)
- Telegram to Matrix (via mautrix-telegram)
- XMPP/Jabber to Matrix (via matrix-bifrost) (planned)
Direct message bridges
The following bridges only support direct messages.
- Facebook Messenger to Matrix (via mautrix-meta) (planned)
- Instagram to Matrix (via mautrix-meta) (planned)
- Twitter to Matrix (via mautrix-twitter)
Voice chat bridges
The following bridges only bridge voice chats.
- Mumble and Discord (via mumble-discord-bridge) (planned)
Media proxies
Active Discord media proxy
As Discord began requiring expiring HMAC validations on media attachments, the Discord bridge now switches to an active proxying approach, before reuploading/re-serving re-encoded optimized media attachments becomes viable. Files delivered via this new approach will be served at dma.ltgc.cc
.
However due to poor design, the active Discord media proxy fails from time to time. We are working on a dedicated active media proxy written in either JS (Deno) or Go.
Passive Discord media proxy
Due to MSC3860 being unsupported on homeservers without conformation of the Matrix 1.7 specification, homeservers will not recognize discord-media.mau.dev
, the public redirecting Discord media repo. To circumvent this, we offer a custom cached Discord media proxy at dmr.ltgc.cc
instead for use with bridges, however it will likely be shut down to public access if we notice it getting abused.
After Discord implemented expirations on media attachment links with HMAC validation, the media proxy now only serves non-attachment files, like avatars, stickers and custom emojis. Since passive media proxy is less costly to run than active media proxies, it's used whenever possible.
Bridge utilisation
Apply for use
Apart from internal use, we also offer bridging services to other entities upon approval with no SLA.
FLOSS projects
- RethinkDNS (Apache 2.0, MPL 2.0)
- Xray (MPL)
MLP fandom communities
Not-for-profit entities
Known issues
Global
- Animated stickers on certain platforms may only get their first frame be bridged, due to varying media codec support on different platforms.
- Double-bridged replies may not work on certain platforms.
- The bridge may become unresponsive when overloaded. You can help us relieve this problem via donations!
Telegram
- Reactions aren't bridged from Telegram.
- The bridge suffers from unresponsiveness or even downtimes due to PostgreSQL. Migration to SQLite3 is currently scheduled.
- Bot messages from Telegram cannot be bridged to other platforms, per Telegram's restriction.
- Senders from other platforms cannot be transparently bridged to Telegram, requiring embedding their display names as message content.
- Member leave events aren't bridged to Matrix, as such the Telegram member list on Matrix is not representative.
Discord
- Due to Discord validating time-sensitive HMAC codes on attachment URLs, media from Discord cannot be bridged currently.
- This was fixed on 27th March 2024, where a combination of active and passive media proxying was deployed.
- Some of the animated stickers were vector images encoded in custom-defined JSON files. As a result, none of the services other than Discord recognizes them.
- The Discord bridge invites bridged accounts to rooms on-demand, and does not bridge member leave events to Matrix, as such the Discord member list on Matrix is not representative.
Ditzy
Ditzy is a transport-agnostic universal multi-message encoding scheme, allowing stateful bidirectional communications regardless of the statefulness of the underlying transport. With the state of the reconstructed tunnel fully decoupled from the underlying transport, possibilities are endless. How Ditzy performs is entirely dependent on implementation.
This project is inspired by Tor HTTP Meek, MIDI 1.0, Reliable UDP and QUIC.
💌 Feel your messages delivered safely by your trustworthy Ponyvillan mailmare!
The first draft was written on 18th Nov 2021, with the next iteration on 5th Feb 2023. The current draft is written on 29th June 2023.
Advantages
- State of reconstructed connections are decoupled from their underlying transports entirely
- Seamless connection migration on connection losses and IP changes
- Total control over data transmission
Disadvantages
- Directional speed penalty when not in stream mode
- Not suitable for time-sensitive applications
- Resource overhead on both servers and clients
- Possible attack vector via decorated messages
Use cases
- Bidirectional communication through incapable infrastructure (e.g. CDNs, serverless functions, request reflectors, fronted containers)
- Connection multiplexing and splitting
- Stablizing communication over unstable networks
- Replacing QUIC where UDP communication is not feasible
Specifications
Reference implementation API docs
- JavaScript
Binary encoding format
Concepts
Meek
Originally, Meek is a technique emulating stateful connections over HTTP, utilized by Tor for its pluggable transports. It is now generalized to refer to any technique reconstructing stateful connections, regardless of the statefulness of underlying transport.
MIDI
MIDI is a standard for real-time communication between devices. It's originally designed for musical instruments, but has found its places in other fields requiring synchronization and/or automation as well, such as stage lighting systems. It could be thought of as a protocol of communicating changes about the states of instruments via a set of standardized messages.
Variable Length Value
Variable Length Value (VLV) is a way of encoding integer values to multiple bytes, utilizing as many bits inside as they want. With VLV, integer values can be as large as they want within reason, and reduce the byte count when the value is smaller with little overhead.
VLV is defined as a part of Standard MIDI File (SMF) Format Specification.
A VLV can take multiple bytes, and all data encoded are stored in Big-Endian format. VLV bytes use the bit before actual values of each byte to indicate whether or not to continue decoding, and the rest to carry actual values.
Examples below.
Bits | Value (hex) | Value (binary) | VLV (binary) | VLV (hex) |
---|---|---|---|---|
7 | 43 | 01000011 | 01000011 | 43 |
6 | 43 | 01000011 | 01000001 00000011 | 4103 |
7 | 1c57 | 00011100 01010111 | 10111000 01010111 | b857 |
7 | ad41296 | 00001010 11010100 00010010 10010110 | 11010110 11010000 10100101 00010110 | d6d0a516 |
RUDP
RUDP is a general-purpose transport running on top of UDP, designed to achieve guaranteed and ordered packet delivery without the overhead TCP brings. The exact protocol is never documented, but RUDP will always have the following features:
- Acknowledgement of received packets
- Flow control and windowing
- Retransmission of lost packets
- Over-buffering
Ditzy attempts to implement some of the features, optionally with twists:
- Acknowledgement of last received packet IDs in each socket
- Retransmission when messages are considered lost
- Backpressure with customizable buffer/high watermark whenever possible
- Transmit-ahead window whenever possible
QUIC
QUIC is a general-purpose transport running on top of UDP, seeking to be a replacement over traditional TCP. It offers various advantages over traditional TCP, with the most notable ones being seamless connection migration and reduced communication latency.
Ditzy aims to achieve seamless connection migration via its client ID binding mechanism with minimal connection overhead.
Specification
Structure
Transmission
Client data socket
|
| Ditzy encoder
| |
| | Client transport
| | |
| | | (the state of the outermost transport is unrelated
| | | to the states of the reconstructed data sockets)
| | v
| | Server transport
| v
| Ditzy decoder
v
Server data socket
Message
Each Ditzy message is formed by directly combining multiple frames together. The structure of each frame is as follows.
Length | Value | Description |
---|---|---|
1 | #Commands | Command ID |
1~4 | (7-bit VLV) | Socket ID |
1~4 | (7-bit VLV) | Frame ID |
1+ | (7-bit VLV) | Payload length |
0+ | (any) | Payload data |
1 | byte | End of payload + (optional) data checksum |
Socket ID
The socket ID is randomly selected between 1
and 268435455
(0xfffffff
, 228 - 1).
Socket ID 0
is reserved for special purposes and is forbidden from transmitting any payload. It is used to deliver signals that could affect all connections of the client.
Frame ID
The frame ID is iterated from 0
to 268435455
(0xfffffff
, 228 - 1) on the side where connections are initiated. When 268435455
is reached, the message ID is expected to roll back to 0
. Frame ID should only be validated and increased in certain commands, check "Step?" to see if they undergo such process.
Length, EoP + Checksum
When Ditzy is set to fast mode (should only be used in safe environments), the payload length value only points to where the EoP byte is located. The EoP byte in fast mode only serves as a confirmation for bounds checking, and thus both sides should only select a random byte that has the 7th bit set to 0 (0~127) to do the job. When the supposed length doesn't match, Ditzy will discard all messages in the bundle completely in case of a decoration attack.
When Ditzy is set to strict mode, the payload length value is ignored, and Ditzy will attempt to validate the checksum once it finds the EoP byte. If the checksum does not match, Ditzy will discard all messages in the bundle completely in case of a decoration attack.
The checksum is calculated by setting the initial value to 63, and performing XOR operations to every byte in the payload. Once this is finished, the calculated value is then inverted, have 1
added. The final value would the the last 7 bits (0b0xxxxxxx
) of the value. Example JavaScript code below.
let ditzyChecksum = (bytes) => {
let checksum = 63;
for (let i = 0; i < bytes.length; i ++) {
checksum ^= bytes[i];
};
return (~checksum + 1) & 127;
};
Commands
IDs between 0
(0x00
) and 31
(0x1f
) are reserved for core functionalities. Extenstions are free to utilize any ID between 32
(0x20
) and 255
(0xff
).
Different commands have different support levels. To meet a certain support level, features of the indicated level must be implemented.
ID | Command | Level | Step? |
---|---|---|---|
0 | Socket close | 1 | No |
1 | Socket open | 1 | No |
2 | Socket aftertouch / signalling | 1 | No |
3 | Jump | 1 | No |
4 | Full payload send | 1 | Yes |
5 | Frame acknowledge | 1 | Yes |
6 | Error | 2 | No |
7 | Implementation exclusive | 2 | No |
8 | Partial payload send | 3 | Yes |
9 | Partial payload send continue | 3 | Yes |
10 | Unordered tailing acknowledgement | 3 | No |
0
: Socket close
Can be initiated bidirectionally.
Response should be exactly the same as request.
Closes a single connection. Payload can be used to carry optional arbitrary printable error messages, UTF-8 encoded. Analogous to 8x nn vv
or 9x nn 00
.
1
: Socket open
Can be initiated bidirectionally.
Response should have the same frame ID as request.
Opens a connection. Payload is used to define suggested Socket timeout in milliseconds optionally. Frame ID must be set to 0
, or the message will be considered invalid.
(Optional) If sent from the receiving end, the value contains would be the final timeout value used in the connection. Analogous to 9x nn vv
.
2
: Socket aftertouch/signalling
Can be initiated bidirectionally.
Response should have the same frame ID as request.
Challenges a connection. Often used to implement socket latency tests. Analogous to cx vv
.
Payload sets challenge type.
Types of aftertouch
0
: Latency test SYN1.1
: Latency test ACK1.2
: Latency test SYN2.3
: Latency test ACK2.
Types of signalling
128
: Bind client ID, must be the very first message of every Ditzy connection. Frame ID contains the desired client ID. Each active connection can only have a client bound to an ID once, or the connection will be terminated to prevent flooding. Server response indicates a bound client ID.129
: Client terminate. Frame ID contains the desired client ID, should match the client ID bound to the transmission session. All sockets managed under the provided client ID will be gracefully closed. Server response indicates a successful queue of graceful client termination.130
: Saturated send buffer. Typically sent from the server to the client, this is used to signal the client to establish more connections with the server to help deplete its send buffer.
3
: Jump
Can be initiated bidirectionally.
No responses are needed for jumps.
Sends a junk frame. The receiving end should ignore jump messages. Useful to implement noise.
4
: Full payload send
Can be initiated bidirectionally.
Use type 5 (payload acknowledge) to send acknowledgements with the same frame ID.
Sends a full message. Analogous to f0 .. .. f7
.
5
: Frame acknowledge
Can be initiated bidirectionally. Only required over unreliable channels.
Sends acknowledgement of the last received sequencial frame.
6
: Error
Can be initiated bidirectionally.
No response is needed for errors.
Sends arbitrary errors without closing the connection.
7
: Implementation exclusive
Can be initiated bidirectionally.
Response should have the same frame ID as request.
Implementation exclusive binary commands. Analogous to f0 .. .. f7
or ff .. ..
8
: Partial payload send
Can be initiated bidirectionally. Certain underlying transports may disable this.
Use type 5 (payload acknowledge) to send acknowledgements with the same frame ID.
Sends a segment of a message. Used to begin and continue sending the segments of a full message. The server should begin to interpret "full payload send" messages as "payload send complete" on the same socket. Analogous to f0 .. ..
.
9
: Partial payload send continue
Can be initiated bidirectionally. Certain underlying transports may disable this.
Use type 5 (payload acknowledge) to send acknowledgements with the same frame ID.
Sends the final segment of a message. The server should interpret "full payload send" messages as "payload send complete" on the same socket. Analogous to f7 .. ..
.
10
: Unordered tailing acknowledgement
Can be initiated bidirectionally. Only required over unreliable channels.
Sends a list of unordered received frames after the last continuously received frame. Used to reduce frame retransmissions when a copy has already been received.
After frame acknowledgement (message type 5
) is sent, unordered tailing acknowledgements could be sent multiple times with the same frame ID as the preceding frame acknowledgement message, as long as the list of acknowledged frames aren't fully sent yet. Frame IDs are all encoded in 7-bit VLVs, with each VLV considered as an element of the list.
Recommended implementation practices
Ideas
Meek as a general terms, covers techniques reconstructing states of duplex sockets over underlying measures of communication. It doesn't have to be constrained to a single set of views. Under ideal circumstances, Meek can achieve full socket state decoupling with arbitrary socket delivery, however reaching those
Generic
Floaty
Floaty is a Caddy plugin implementing customizable rolling random IDs on a per-host basis, providing easy access via placeholders in Caddy.
Uses include:
- Loopback prevention
- Multi-hop debugging
- Forced time-based rolling sticky hash wherever needed
All with little to no traceability, if the rolling duration is set correctly.
Usage
Caddyfile
In the global section, set Floaty to run before request header processing.
{
order floaty before header
}
In any of the server blocks, use the floaty
directive to prepare the respective rolling random IDs. The syntax is as follows.
floaty [length [rollDuration]] [{
[fieldId [length [rollDuration]]]
}]
Whenever Floaty is initialized, the placeholder http.floaty
would become available within that server block, where placeholders from HTTP handlers are accessible.
Generated ID lengths can be any value between 4
and 96
, and out-of-bound values will be clamped into this range. By default, length is set to 8
. Longer IDs may cause excessive resource usage.
Roll duration can be set to any value above 10 seconds with millisecond precision, if supported by the Go duration syntax. It's set to 15 minutes by default. A lower rolling duration may cause excessive resource usage.
When a request is received, Floaty will attempt to check if any of the needed request IDs have expired. Only when expired upon receiving a request, will Floaty begin to regenerate a new ID. This will add a little bit of overhead to each request, however it will prevent unnecessary ID rerolls when not in use.
Examples
Adding a response header with a default Floaty ID:
http://:8080 {
...
floaty
header X-Floaty {http.floaty}
...
}
Adding a request header with a Floaty ID to reverse proxies, while blocking requests with a matching Floaty ID:
http://:8080 {
...
floaty {
instance_id 12 10m
source_id 12 5m
}
...
@directLoopback {
header X-Previous-Hop {http.floaty.instance_id}
}
@indirectLoopback {
header X-Source-Hop {http.floaty.source_id}
}
respond @directLoopback "Loopback denied" 403
respond @indirectLoopback "Loopback denied" 403
...
reverse_proxy {
...
header_up X-Previous-Hop {http.floaty.instance_id}
header_up ?X-Source-Hop {http.floaty_source_id}
}
...
}
gel
⛏ Rolling server bases, batteries included.
Gel is a set of scripts to quickly prepare supported base Linux distributions for use in cloud, aiming to lessen the burden interacting with servers. For Alpine Linux, it comes with a simple OpenRC wrapper to get several systemctl
commands working for OpenRC.
Gel is extensively used throughout Lightingale Community's infrastructure, either for host servers or for LXC containers. Read more on infrastructure.
Flavours
Gel mostly comes with two flavours for each supported base distribution: slim and full.
The full flavour targets all sorts of servers. Unless storage is severely constrained, this is the flavour to go for.
The slim flavour targets container hosts and VM hosts, which barely gets interacted directly, but still requires the ease-of-use found in the full version of Gel. It can also be used in other scenarios, if the full flavour contains packages you'd prefer not to be present on your system.
Full list
Slim | Full | Name | LXC ready? | LXC base size |
---|---|---|---|---|
slimalp | alpine | Alpine Stable | No | 11 MiB |
slimalma | alma | AlmaLinux | Yes | 433 MiB |
slimdeb | debian | Debian Stable | Yes | 363 MiB |
slimleap | leapsuse | openSUSE Leap | Yes | 190 MiB |
slimsuse | opensuse | openSUSE Tumbleweed | No | - |
slimrock | rocky | Rocky Linux | Yes | 433 MiB |
photon | N/A | Photon Linux | No | N/A |
Usage & Security
Installation
Native
For bare-metal, virtual machines and LXC containers. Do not run native install scripts other than on new machines.
- On any of the supported distros, make sure
curl
is available. - Execute
sh <(curl -Ls https://github.com/ltgcgo/gel/releases/latest/download/install.sh)
. (orsh <(curl -Ls https://codeberg.org/ltgc/gel/releases/download/latest/install.sh)
, useGEL_SLIM=1
to enable slim installation) - Connect via SSH with
ssh -p 1122 <serverIP>
. User passwords won't change, but SSH settings will. See the SSH section for details.
Containers
Container images are only offered as a convenient way of evaluating the installations.
- Spin up one of the available Gel flavours.
- Images are available on the Docker Hub if you want to save time. Use
podman pull docker.io/ltgc/gel:<flavour>
to pull the images. - Or feel free to build the image yourself with
./shx up <flavour>
.
- Images are available on the Docker Hub if you want to save time. Use
- Connect to the SSH with
ssh -p 1122 [email protected]
. The default password isroot
.
Additional considerations
Offloading RAM
Warning
Avoid offloading RAM in guests as much as possible, when the root host you have access to of the guest could have RAM offloading enabled instead.
Gel does not configure RAM offloading automatically in any way.
swap
When enabled, the system will swap memory pages used less frequently off the active RAM, freeing up system resources whenever possible. This will lessen the impact of memory hungry processes, at the cost of disk wear and tear.
swap
comes in two types, disk partition and files. Swapfiles are generally not supported in certain file systems like btrfs
, however they're much more flexible compared to disk partitions, since they could be created without threatening the underlying filesystem and can have multiple active simultaneously, as such swapfiles should be preferred whenever possible.
Depending on the actual size of RAM and remaining vacancy on the disk, the chosen size of the swap is generally between 50% and 200% of it. Generally for a system with small RAM (e.g. 1 GB), a swap with the size of 2 GiB is desired; for a system with large RAM (e.g. 32 GB), a swap with the size of 16 GiB could be considered sufficient. If you want to have hibernation enabled on your system, the swap size should be no smaller than the physical RAM.
To create a 2 GiB swapfile at /swapfile
(1048576 * 1024 * 2), run the following commands as root
.
dd if=/dev/zero of=/swapfile bs=1048576 count=2048
mkswap /swapfile
chmod 600 /swapfile
To enable the swapfile immediately, run the following command. Disabling the swapfile only needs to change the swapon
command to swapoff
.
swapon /swapfile
If the swapfile at /swapfile
needs to be loaded automatically across reboots, open /etc/fstab
and append the following line.
/swapfile none swap sw 0 0
zswap
Notice
All steps demonstrated below do not persist across reboots. Read Setting up Zswap in Debian 11 GNU/Linux for persistence.
Requires swap
to be enabled. zswap
creates a compressed cache in RAM for system to swap pages off to, before the system decides to offload to the on-disk swap instead. Enabling zswap
on top of swap
helps to lessen the burden dumped onto the disk, make memory usage more efficient, while increasing responsiveness, as some of the infrequently accessed pages now resides in the much-faster RAM instead.
To see the current configurations for zswap
, run the following command.
grep -R . /sys/module/zswap/parameters
Stastistics for zswap
is also available.
grep -R . /sys/kernel/debug/zswap
Enabling zswap
is as easy as running the following command as root
.
echo 1 > /sys/module/zswap/parameters/enabled
zswap
will use at most 20% of your actual RAM to store the compressed cache. Let's say you want to adjust the allocation percentage to 25%.
echo 25 > /sys/module/zswap/parameters/max_pool_percent
To see the current compression factor of the system, run the commands below.
cd /sys/kernel/debug/zswap
perl -E "say $(cat stored_pages) * 4096 / $(cat pool_total_size)"
Distributions typically choose lz4
or lzo
as the compression algorithm for zswap
, however zstd
is also available for more powerful devices. lzo
is slightly slower than lz4
for a slightly higher compression factor. lz4
is recommended for most use cases, which could be set with the command below.
echo lz4 > /sys/module/zswap/parameters/compressor
A list of typical compression factors is available below, as well as the source of the data.
Algorithm | Factor |
---|---|
lz4 | 2.1 |
lzo | 2.15 |
zstd | 3 |
Alpine Linux
Additional repos
Gel needs the community repo to be enabled in order to function.
glibc compatibility
While not done by default, Alpine installations come bundled with a helper script configuring glibc
compatibility. It may not work under every situation, but it should handle most use cases. root
is required.
bash ~/gel/distro/sh/glibc.sh
openSUSE Leap
doas
is not available on the platform. The regular sudo
is used instead.
Security
Privilege elevation
To reduce attack surface, Gel will attempt to replace sudo
with doas
from OpenBSD. By default, only the root
user is allowed to use the doas
command.
To allow other users to execute the doas
command as root
, append the following directives to a new line in /etc/doas.conf
.
permit keepenv <user> as root
Make sure there is a trailing new line at the end of /etc/doas.conf
. If not, doas
command will not work.
SSH
The SSH settings will be changed with a relatively more secure one, except for permitting password logins to prevent you from losing access with an unfinished setup.
After finishing the automated Gel setup, do the following to secure your SSH access.
- If the password of the
root
user wasn't set by you, change it to a stronger one. - Add a custom new user, which would be used for SSH logins.
- As the newly-created custom user, add the public keys used for SSH authorization.
- Keep the current SSH session active, and login as the new user to ensure access to machine is not lost.
- Allow the new user to use the
doas
command and verify. See the Privilege elevation section for details. - Add the new user to the
sshuser
group, added automatically by the setup script. Example:usermod -aG sshuser <user>
. - In
/etc/ssh/sshd_config
, do the following.
- Set
PermitRootLogin
fromyes
tono
. - Uncomment
AllowGroups
andDenyGroups
. - (optional) Change the listening port from
1122
to another.
- Restart
sshd
withsystemctl restart sshd
.
Container setup
LXC
This section documents the processes of configuring LXC on distros supported by Gel.
Installation
- Alpine:
apk add lxc lxcfs lxc-download lxc-bridge
- Debian:
apt install lxc lxcfs lxc-templates uidmap libpam-cgfs bridge-utils --no-install-recommends
- openSUSE:
zypper in lxc
- Rocky Linux/AlmaLinux:
dnf install lxc lxcfs lxc-templates
- Photon: N/A
Config files
- Container config files:
/var/lib/lxc/<name>/config
Container creation from official templates
When creating containers from official templates, you'll be presented with a list of available distros, alongwith release names and CPU architectures. Visit for the full list.
To select a source image directly without the selection prompt, use the following command.
lxc-create -t download -n "<name>" -- --dist <distro> --release <release> --arch <arch>
Assign static IPv4 addresses
From Setup network bridge in lxc-net.
Create /etc/lxc/dhcp.conf
. The definitions go in dhcp-host=<containerName>,<ip>
format. Example below.
dhcp-host=deerHorny,10.0.3.114
dhcp-host=polakCute,10.0.3.115
If /etc/default/lxc-net
exists, have the following line inside to tell lxc-net
use the DHCP config before restarting the lxc-net
service.
LXC_DHCP_CONFILE=/etc/lxc/dhcp.conf
Enable autostart
In the container config, have the following lines.
# Enable autostart
lxc.start.order = <startOrder> # Lower is earlier
lxc.start.auto = 1
lxc.start.delay = 4 # In seconds
Enable nested containerization
In the container config, have the following lines.
# Allow nested containerization
lxc.include = /usr/share/lxc/config/nesting.conf
Enable FUSE
In the container config, have the following lines.
# Enable FUSE
lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,rw 0 0
Enable TUN
In the container config, have the following lines.
# Enable TUN
lxc.mount.entry = /dev/net dev/net none bind,create=dir
lxc.cgroup2.devices.allow = c 10:200 rwm
Limit CPU and RAM usage
From Memory Controller ・cgroup2.
In the container config, follow the example provided below.
# Limit CPU and RAM
lxc.cgroup2.memory.min = 268435456
lxc.cgroup2.memory.max = 536870912
lxc.cgroup2.cpu.max = 500000 1000000
This sets the container to...
- Use at most 512 MiB of RAM (hard limit), with 256 MiB guaranteed (hard limit).
- Allows using half of a core's worth of computing power.
Raise limits on opened files
From Proxmox ulimit hell: how to really increase open files ?
In /etc/sysctl.conf
, make sure the following lines are present. Feel free to adjust the values to your needs.
fs.inotify.max_queued_events = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_user_watches = 1048576
vm.max_map_count = 262144
In /etc/security/limits.conf
, have the following lines. Feel free to adjust the values to your needs.
* soft nofile 1048576 unset
* hard nofile 1048576 unset
root soft nofile 1048576 unset
root hard nofile 1048576 unset
* soft memlock 1048576 unset
* hard memlock 1048576 unset
In the container config, have the following lines. Feel free to adjust the values to your needs.
# Raise limits on opened files
lxc.prlimit.nofile = 1048576
Inside the container, have the following lines in /etc/security/limits.conf
. Feel free to adjust the values to your needs.
* soft nofile 1048576 unset
* hard nofile 1048576 unset
root soft nofile 1048576 unset
root hard nofile 1048576 unset
* soft memlock 1048576 unset
* hard memlock 1048576 unset
Reboot the host and the container(s) to apply the changes.
Manual unprivileged container setup
Extended from this blog post.
The containers configured these way are unprivileged, however they are owned by root
, this is due to the problems surrounding unprivileged containers when owned by unprevileged users.
You can create the container before or after assigning subordinate IDs manually, but it must be done before modifying the container's configuration file. All commands in this section assume root
privilege unless told explicitly otherwise.
Select and map subordinate IDs
Subordinate IDs permit mapping a range of IDs to a user, allowing the container to run unprivileged without the typical downsides. To avoid conflicts, it's advised to reserve a relatively large gap between different unprivileged containers in multiples of 65536
, the minimum required amount of subordinate IDs for running unprivileged containers of any kind.
You'll be editing /etc/subuid
for user IDs, and /etc/subgid
for group IDs. Both files follow the same scheme: <username>:<startID>:<idCount>
. For example, hornydeer:2097152:65536
maps IDs from 2097152
to 2162687
to user hornydeer
, 65536 IDs in total. Comments are not allowed there.
As an example, we're setting the start UID and start GID to 1148576, and allocate 65536 IDs for use by the container. If you intend to have an LXC container act as a container host, you may need to scale up the count of IDs. Write the following line to both /etc/subuid
and /etc/subgid
.
root:1148576:65536
If you're going to run unprivileged containers inside the target unprivileged LXC, below is an example reserving enough subordinate IDs for use.
root:1148576:262144
Apply mapped IDs in configuration
To apply the mapped IDs, head to /var/lib/lxc/<containerName>
and modify the config
file. According to the containerized distro chosen, there may be seperate user namespace profiles, so switch to those if you encounter problems.
# Remapped user and group IDs
lxc.include = /usr/share/lxc/config/userns.conf
lxc.idmap = u 0 1148576 65536
lxc.idmap = g 0 1148576 65536
If you've chosen to use the larger ID space for unprivileged containers above, below is the corresponding example.
# Remapped user and group IDs
lxc.include = /usr/share/lxc/config/userns.conf
lxc.idmap = u 0 1148576 262144
lxc.idmap = g 0 1148576 262144
Change owner of the container root
Before the LXC container could be started, the owner of its root folder must be set as the beginning subordinate ID, 1148576
in the case of the example. Run the following command.
chown -R 1148576:1148576 /var/lib/lxc/<containerName>/rootfs
Also ensuring the container itself can access its own filesystem for good measure.
chmod 755 /var/lib/lxc # Most distros already has this as default
chmod 755 /var/lib/lxc/<containerName>
chmod 755 /var/lib/lxc/<containerName>/rootfs
chmod 640 /var/lib/lxc/<containerName>/config
nftables
The default config for nftables
looks like this.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter;
}
chain forward {
type filter hook forward priority filter;
}
chain output {
type filter hook output priority filter;
}
}
- It's possible to match multiple ports at the same time. Instead of specifying a single port number (e.g.
443
), use curly braces:{443, 8443}
. Ranges can also be specified:1024-2047
. - If a certain rule only applies to traffic originating from certain interfaces, prefix the rule with
iif <interface>
. Can be a single interface (e.g.iif "eth0"
) or multiple (e.g.iif {"eth0", "ens15"}
).
Transparent service exposure
From nftables: forwarding without masquerading, Quick reference: nftables in 10 minutes.
Because the LXC host is the network gateway of all LXC containers, service exposure without masquerading is entirely possible, allowing services inside LXC slices to obtain the actual IP addresses. Add the block below to begin specifying rules for service exposure.
If you want to expose services on both IPv4 and IPv6, rules will need to be duplicated. It's also important to note that containers must have the respective IP version available, for it to be exposed transparently. LXC 6.0.0 and newer has IPv6 addresses assigned automatically, while 4.0.0 and newer can have IPv6 manually configured. Only LXC 5.0.0 and newer supports IPv6 connectivity behind NAT.
table ip nat {
chain prerouting {
type nat hook prerouting priority filter;
# Insert new rules for IPv4 here
}
}
table ip6 nat {
chain prerouting {
type nat hook prerouting priority filter;
# Insert new rules for IPv6 here
}
}
Let's say we want to expose 10.0.3.2:443
for anyone on the Internet to access on port 443.
tcp dport 443 dnat to 10.0.3.2
If the port numbers are not the same, the port will need to be overriden.
tcp dport 443 dnat to 10.0.3.2:8443
Or multiple ports are to be exposed without overriding the port.
tcp dport {443, 8443} dnat to 10.0.3.2
tcp dport 512-1023 dnat to 10.0.3.2
Or only expose access to (a) certain interface(s).
iif "eth0" tcp dport 443 dnat to 10.0.3.2
iif {"eth0", "vlan0"} tcp dport 443 dnat to 10.0.3.2
An example of a rule with similar use under IPv6.
iif "he-ipv6" tcp dport {80, 443} dnat to [fc11:4514:1919:810::ff:fe00:2]
Flush your rulesets with the command below, so LXC slices will still have connectivity via NAT after flushing.
nft -f /etc/nftables.conf; systemctl restart lxc-net
Network access restriction - IP-based
Inspired by How to restrict network access of LXC container.
Notice
nftable
-based network access control is still under investigation. Problems are expected to rise.If fine-grained access control like destination-matching (e.g. domain) is desired, use EEP with transparent proxy on the host instead.
Since the current
nftables
approach requires static IPs to be assigned first, but there is no way found to have IPv6 addresses assigned statically, IPv6 access might need to be disabled for the container.
The inet filter forward
section is where network access of individual containers is filtered.
If whitelisted network access is desired, add a rule in the scheme shown below to the end of the section for that specific container.
iif "lxcbr0" ip saddr 10.0.3.2 drop;
Then add allowed access ranges before the final drop to grant access to specific addresses. If problems occur with transparent service exposure, they will need to be made exempt.
iif "lxcbr0" ip saddr 10.0.3.2 ip daddr 10.0.3.0-10.0.3.255 accept;
Or if network access isn't whitelisted, and access to certain ranges are to be blocked, add a rule in the scheme shown below.
iif "lxcbr0" ip saddr 10.0.3.2 ip daddr 10.0.3.2-10.0.3.255 drop;
Podman
This section documents the processes of setting up Podman on distros supported by Gel. To get Podman functioning, fuse
and tun
support has to be present.
If you're running Podman inside an (unprivileged) LXC container, make sure the steps listed below have all been applied to the host LXC container, all of which could be found above.
- Assign a larger ID space
- Enable FUSE
- Enable nested containerization
- Enable TUN
- Raise limits on opened files
Installation
Warning
- Certain distros (e.g. Debian) may not have a functioning version of
crun
. Installcrun
from Nixpkgs when such errors are encountered.- A few distros like Photon do not have
podman-compose
bundled.- If you encounter warnings regarding
/
not being shared, fix temporarily withmount --make-rshared /
. Read Alpine Wiki for further info.
- Alpine:
apk add podman podman-compose
- Debian:
apt install podman podman-compose
- openSUSE:
zypper in podman podman-compose
- Rocky Linux/AlmaLinux:
dnf install podman podman-compose
- Photon:
tdnf install podman
After installation, run a "Hello World" container to ensure everything works correctly.
podman run --rm hello-world
If problems occur, below is an example command for debugging.
podman run --security-opt="seccomp=unconfined" --log-level=debug --rm hello-world
Manual subordinate ID assign
Note Distros may already have this section configured automatically. Only follow this section when you encounter problems.
Explanations about subordinate IDs are available in previous sections. If you encounter Podman complaining about IDs, below is an example inside unprivileged LXC containers to apply in both /etc/subuid
and /etc/subgid
.
<username>:65536:131072
Run podman system migrate
whenever the assigned subordinate ID space changes.
Octavia
Octavia is an event-driven multi-standard MIDI state-tracking library.
Features
- Free, libre and open-source, under GNU LGPL v3.0.
- Behaves like a real MIDI module.
- Developed with Firefox and an open Web in mind.
- Supports 8 ports, 128 channels, 512-voice polyphony maximum.
- Built-in support of several standards, multiple plug-in cards, and tons of devices.
- Tells when MIDI programming errors are spotted, reducing chances of faulty programming.
- Available in JavaScript (browser and Deno).
- No modification required to run in Tor Browser, Bromite and LibreWolf.
- Wide support of bank mapping and bitmaps via
midi-db
.
Dev Talks
We're now hosting a new place to handle development talks! If you don't have a GitHub account, or just prefer to report bugs or give suggestions in a more casual way, feel free to chat with us with links below!
- Fediverse (Mastodon): @[email protected]
- Telegram channel: @ltgc_t
- Telegram group chat: Click to join DTM Hub
Further documentation
Demo usage
Support coverage
Implementation
SysEx documentation
API documentation
state.mjs
: the core processing unitbasic.mjs
: the basis for visualizersbridge.mjs
: the basis for middlewaredisp.mjs
: ready-made example visualizersmiddle.mjs
: ready-made middlewaremicc.mjs
: streaming assembler and disassembler
Visualizer
Warning
This section covers how to use the visualizers bundled as public demos, as such it does not reflect the behaviour of the respective modules themselves.
Things to notice
Rendering
- Visualizers have strict render resolution constraints. For the best results, it is advised to only render while conforming to those resolution constraints.
- Visualizers are all designed to render at 50 FPS. Some visualizers may offer custom framerates, however it is advised to only render at a framerate less than or equal to the capture framerate. Visualizers offered by Octavia, especially ones displaying individual notes, feature an algorithm guaranteeing notes to be displayed each frame. As such, a framerate too high will cause visualizers fail to show display immediate notes.
Usage
Input selectors
To begin using visualizers, you must select how you want to accept events. There are several options available.
Load MIDI files
You can load standard MIDI files (.mid
or .kar
), load SysEx blobs (.syx
), load voice remapping tables (.mdat
) or custom voice bank files with this action. An audio track must be loaded with the MIDI file.
Click on the "MIDI" button to load respective files. For multi-port MIDI files, port declarations via standard meta events and XGworks port assign events are all supported. Refer to multi-port extensions for details.
Load synced audio tracks
You can load an audio file synced to the accompanying MIDI file with this action. A MIDI file must be loaded with the audio file.
Click on the "audio" button to load synced audio tracks.
Receive from the shared line-in bus
When active, the visualizer will receive events from the shared line-in bus. Events received are directly emitted from the middleware without any modifications. Read MIDI I/O routing to acknowledge how to configure how MIDI events are received.
Click on the "line in" button to begin receiving from the bus. The button may appear as just "line" in some visualizers.
Receive from the shared line-out bus
Same as "line-in", but the events received will be processed by the Octavia core present on the middleware panel page. As such, events could've been modified if polyfilling or real-time translation has been enabled. Read MIDI I/O routing to acknowledge how to configure how MIDI events are received.
Click on the "line out" button to begin receiving from the bus. The button may not be present in certain visualizers.
Mode selectors
Octavia supports a range of modes ensuring correct state handling. Upon mode switches, the corresponding mode selector will be highlighted. Clicking on the mode selectors will change the global fallback mode of the core respectively.
Visualizer-specific options
Some visualizers come with additional options for configuring behaviour and look. These options are usually quite self-explanatory, but explanations for certain options considered obscure are also available below.
Demo selector
Octavia have two demo selection systems used by various public demo visualizers: letter ID and double selection.
Letter ID
This is the simplest selection system used. Demos are indexed by a unique letter from different writing systems. Simply hitting on one of the letters loads the respective demo, while depending on the visualizer, hovering over the letters may either expose the file name or some detailed info.
Double selection
Demos are grouped by collections. To select a specific demo, first select the desired collection, then select the desired file. Pressing the "load" button will load the demo, while long presses or alt clicks will load and play the demo.
Explore
Toggle authentic mode ("true mode")
To allow visualizers function normally after possible legal strikes, most visualizers render under the "libre" mode. In libre mode, assets used are replaced with libre counter parts as much as possible, with famous examples like the libre 5 by 7 font from SynPix.
However, it is also possible for certain visualizers to try resemble the real screens as much as possible under a specific rendering mode. This mode is dubbed "true mode" or "authentic mode", and can be accessed by appending #trueMode
to the URLs of visualizers, or by pressing T
.
Changing channels/parts
Single-focus visualizers can only display information from one channel at a time. Focused channel can be changed by clicking on the vertical edges (left and right edges) of such visualizers, or scrolling on such visualizers.
For production purposes however, it's recommended to embed channel switch SysEx messages among the events instead. Most, if not all Octavia visualizers, support the Yamaha MU channel switch SysEx message.
Changing display modes
Certain visualizers offer various rendering modes. You can switch between modes by clicking on the top or the bottom edges of these visualizers.
Top | Bottom | |
---|---|---|
QY | song info, part info | N/A |
PSR | song title, voice name, rhythm | measure, tempo |
Middleware
Audio Effects
Audio effects
Octavia supports tracking a range of audio effects applied on supported targets. For maximum compatibility, Octavia has seven available slots reserved for effect sends, which correspond to reverb, chorus, variation and four insertions in order.
Each slot isn't dedicated to what that slot is primarily used for, but rather allocated and controlled by the CC registers they are assigned to by default (cc91, cc93, cc94, cc16-19). For example, the variation slot (cc94) is taken away by delay effects when in GS mode, while the reverb and chorus slot could be taken away by any effect desired in X5DR or NS5R mode.
Due to varied setups, each effect also isn't just bound to the CC registers they are assigned to. They can also listen on other CC registers, or even multiple if they wish.
Comparison table
Singular effect
Reverb
Yamaha XG | GS Reverb | GS Insertion | KORG AI² |
---|---|---|---|
Hall (1, 2, M, L) | Hall (1, 2) | Hall (1, 2) | Hall (normal, ensemble, concert) |
Room (1-3, S, M, L) | Room (1-3) | Room (1, 2) | Room (normal, large) |
Stage (1, 2) | Stage (1, 2) | Stage | |
Plate (XG, GM) | Plate | Plate (wet, dry) | |
Delay (LCR, LR) | Delay | Delay (stereo) | Delay (stereo) |
Echo | |||
Cross Delay | Panning Delay | Delay (3-tap, 4-tap, mod, 3D, trem.c.) | Delay (cross, dual, tap 1-3) |
Early Reflection (1, 2) | Early Reflection (1-3) | ||
Gate (forward, reverse) | Gate (forward, reverse, sweep 1-2) | ||
White Room | |||
Tunnel | |||
Canyon | |||
Basement | |||
Karaoke (1, 2, 3) | |||
Spring |
Chorus
Yamaha XG | GS Chorus | GS Insertion | KORG AI² |
---|
Delay
Yamaha XG | GS Delay | GS Insertion | KORG AI² |
---|
Miscellaneous
Yamaha XG | GS Insertion | KORG AI² |
---|
Dual effect
Mutual
- X: Yamaha XG
- G: Roland GS
- A: KORG AI²
Rev | Cho | Ovr | Dst | Enh | Fln | Dly | Rot | Phs | Amp | Cmp | AWa | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Rev | A | |||||||||||
Cho | G | G | G | G | GA | |||||||
Ovr | G | G | G | XGA | XG | G | XG | |||||
Dst | G | G | XGA | X | X | X | ||||||
Enh | G | G | G | |||||||||
Fln | G | G | G | G | GA | |||||||
Dly | A | GA | XGA | XGA | G | GA | A | A | A | |||
Rot | XG | X | A | X | X | |||||||
Phs | G | A | ||||||||||
Amp | X | |||||||||||
Cmp | X | |||||||||||
AWa | XG | X |
RPN/NRPN values
RPN/NRPN values
Voice data maps
Types
ID maps
TSV files mapping MSB, PRG and LSB into voices.
MSB
: cc0 (bank MSB) value of the voice.PRG
: PC (program change) value of the voice.LSB
: cc32 (bank LSB) value of the voice.NME
: 8-character ID of the voice.ELC
: Element count (minus one) of the voice.- When set to
0
, the voice takes up one element.1
for two,2
for three, the same goes on. - When set to
16
, the voice is treated as a drum kit. - When set to
17
, the voice is treated as a voice menu. - Any value above is not defined.
- When set to
DRM
: Drum map ID used. Can also be used by voice menus.VXP
: Voice property map ID used.
Drum maps
Custom script files defining properties of drum kits and their voices.
drm
defines the current drum map ID to write to.- e.g.
drm xgStdKit
switches toxgStdKit
.
- e.g.
dcp
copies parameters from a set drum kit.- e.g.
dcp xgStdKit
copies parameters fromxgStdKit
to the current drum kit.
- e.g.
nno
defines the current drum note number to write to.- e.g.
nno 39
switches to39
.
- e.g.
npw
writes multiple parameters to a single drum note.npw <note> <exclusiveGroup> <elementCount>
neg
sets the exclusive group (aka. alternate assign) of the current note number. Defaults to0
(disabled).nec
sets the note element count of the current note number. Defaults to1
.
Voice property maps
TSV files describing certain properties of individual voices.
VXP
: Voice property ID
VL properties
BNS
: VL Breath Noise Source0
: None1
: Modulation wheel2
: Blow strength4
: Throat formant
BNM
: VL Breath Noise Amplitude from Mod Wheel0
: -164
: 0127
: 1
BNB
: VL Breath Noise Amplitude from Blow StrengthBNT
: VL Breath Noise Amplitude from Throat FormantBNV
: VL Breath Noise Value Floor-128
: -10
: 0127
: 1
BND
: VL Breath Noise Blow Strength Decay DurationBNL
: VL Breath Noise Blow Strength Decay LevelBAD
: VL Breath Attack Duration, specified in millisecondsBAL
: VL Breath Attack Level0
: -64 (from a very wide triangle)64
: 0 (no attack EG)127
: 63 (from a very narrow triangle)
BDD
: VL Breath Decay Duration, specified in millisecondsBDL
: VL Breath Decay Level0
: Decay to 0 (pluck)64
: Decay to 50.4%127
: No decay
TOM
: VL Throat Formant Oscillation from Modulation0
: None127
: Maximum
TOS
: VL Throat Formant Oscillation Speed, specified in milliseconds when a cycle completes.TOT
: VL Throat Formant Oscillation Type0
: None1
: Single oscillator2
: Double oscillator (single oscillator modulated by an additional LFO)
TFS
: VL Throat Formant Source0
: Constant until set1
: cc1 (Modulation wheel)- ...
13
: cc13 (default VL throat formant source)- ...
32
: Always constant
TFV
: VL Throat Formant Value, the fixed default value for certain instruments.
Implementation Table
MIDI Implementation Chart
Function | Recognized | Remarks | |
---|---|---|---|
Basic Channel | Default | ✓ 1-16 | |
Changed | ✓ 1-16 | Supports up to 128 channels. | |
Note number | 0-127 | ||
Mode | Default | 3 | |
Messages | ✓ 3, 4 | ||
Velocity | Note on | ✓ 9nV=1-127 | |
Note off | ✓ 9nV=0 8n | ||
Aftertouch | Key | ✓ | |
Channel | ✓ | ||
Pitchbend | ✓ | 0-24 semitone steps 14-bit resolution |
|
Control Change | 0 | ✓ | MSB Bank Select |
1 | ✓ | Modulation | |
2 | ✓ | Breath | |
4 | ✓ | Foot | |
5 | ✓ | Portamento Time | |
6 | ✓ | MSB (N)RPN Data Commit | |
7 | ✓ | Volume | |
8 | ✓ | Balance | |
10 | ✓ | Pan | |
11 | ✓ | Expression | |
12 | ✓ | General-purpose effect | |
13 | ✓ | General-purpose effect | |
16 | ✓ | General-purpose sound | |
17 | ✓ | General-purpose sound | |
18 | ✓ | General-purpose sound | |
19 | ✓ | General-purpose sound | |
32 | ✓ | LSB Bank Select | |
38 | ✓ | LSB (N)RPN Data Commit | |
64 | ✓ | Sustain (Hold) | |
65 | ✓ | Portamento | |
66 | ✓ | Sostenuto | |
67 | ✓ | Soft Pedal Store only |
|
68 | ✓ | Legato Store only |
|
69 | ✓ | Hold 2 Store only |
|
70 | ✓ | Timbre Variation Store only |
|
71 | ✓ | Resonance | |
72 | ✓ | Release Time | |
73 | ✓ | Attack Time | |
74 | ✓ | Brightness | |
75 | ✓ | Decay Time | |
76 | ✓ | Vibrato Rate | |
77 | ✓ | Vibrato Depth | |
78 | ✓ | Vibrato Delay | |
84 | ✓ | Portamento Source Note | |
88 | ✓ | High Resolution Velocity Store only |
|
91 | ✓ | Effect 1 Send (Reverb) | |
92 | ✓ | Effect 2 Send (Tremolo) | |
93 | ✓ | Effect 3 Send (Chorus) | |
94 | ✓ | Effect 4 Send (Variation/Delay) | |
95 | ✓ | Effect 5 Send (Phaser) | |
96 | ✓ | Data Increment | |
97 | ✓ | Data Decrement | |
98 | ✓ | LSB NRPN | |
99 | ✓ | MSB NRPN | |
100 | ✓ | LSB RPN | |
101 | ✓ | MSB RPN | |
120 | ✕ | All Sound Off | |
121 | ✓ | All Controllers Reset | |
123 | ✓ | All Notes Off | |
124 | ✕ | Omni Off Same as cc123 |
|
125 | ✕ | Omni On Same as cc123 |
|
126 | ✓ | Mono | |
127 | ✓ | Poly | |
128 | ✓ | Dry level (internal) | |
129 | ✓ | VL Breath Strength (internal) | |
130 | ✓ | VL Pressure (internal) | |
131 | ✓ | VL Embouchure (internal) | |
132 | ✓ | VL Tonguing (internal) | |
133 | ✓ | VL Scream (internal) | |
134 | ✓ | VL Breath Noise (internal) | |
135 | ✓ | VL Growl (internal) | |
136 | ✓ | VL Throat Formant (internal) | |
137 | ✓ | VL Harmonic Enhancer (internal) | |
138 | ✓ | VL Damping (internal) | |
139 | ✓ | VL Absorption (internal) | |
140 | ✓ | VL Filter (internal) | |
141 | ✓ | VL Amplitude (internal) | |
142~149 | ✓ | DX Carrier Level 1~8 (internal) | |
150~157 | ✓ | DX Modulator Level 1~8 (internal) | |
Registered Parameters | 0x0000 |
✓ | Pitch Bend Range/Sensitivity |
0x0001 |
✓ | Fine Tuning | |
0x0002 |
✓ | Coarse Tuning | |
0x0005 |
✓ | Modulation Depth | |
0x3d00 |
✕ | 3D Azimuth Angle | |
0x3d01 |
✕ | 3D Elevation Angle | |
0x3d02 |
✕ | 3D Gain | |
0x3d03 |
✕ | 3D Distance Ratio | |
0x3d04 |
✕ | 3D Max Distance | |
0x3d05 |
✕ | 3D Gain at Bound | |
0x3d06 |
✕ | 3D Reference Distance Ratio | |
0x3d07 |
✕ | 3D Pan Spread Angle | |
0x3d08 |
✕ | 3D Roll Angle | |
Non-Registered Parameters | 0x0108 |
✓ | Vibrato Rate Redirected to cc76 |
0x0109 |
✓ | Vibrato Depth Redirected to cc77 |
|
0x010a |
✓ | Vibrato Delay Redirected to cc78 |
|
0x0120 |
✓ | Brightness (LPF Cutoff) Redirected to cc74 |
|
0x0121 |
✓ | Resonance Redirected to cc71 |
|
0x0124 |
✓ | HPF Cutoff | |
0x0130 |
✓ | EQ Bass Gain | |
0x0131 |
✓ | EQ Treble Gain | |
0x0134 |
✓ | EQ Bass Frequency | |
0x0135 |
✓ | EQ Treble Frequency | |
0x0163 |
✓ | Attack Time Redirected to cc73 |
|
0x0164 |
✓ | Decay Time Redirected to cc75 |
|
0x0166 |
✓ | Release Time Redirected to cc72 |
|
0x14rr |
✓ | Drum Brightness (LPF Cutoff) | |
0x15rr |
✓ | Drum Resonance | |
0x16rr |
✓ | Drum Attack Time | |
0x17rr |
✓ | Drum Decay Time | |
0x18rr |
✓ | Drum Coarse Tuning | |
0x19rr |
✓ | Drum Fine Tuning | |
0x1arr |
✓ | Drum Level | |
0x1crr |
✓ | Drum Pan | |
0x1drr |
✓ | Drum Reverb Send | |
0x1err |
✓ | Drum Chorus Send | |
0x1frr |
✓ | Drum Variation/Delay Send | |
0x24rr |
✓ | Drum HPF Cutoff | |
0x30rr |
✓ | Drum EQ Bass Gain | |
0x31rr |
✓ | Drum EQ Treble Gain | |
0x34rr |
✓ | Drum EQ Bass Frequency | |
0x35rr |
✓ | Drum EQ Treble Frequency | |
Program Change | ✓ 0-127 | ||
System Exclusive | General MIDI | ✓ | |
General MIDI rev. 2 | ✓ | ||
YAMAHA XG | ✓ | ||
YAMAHA PLG-150AP | ✕ | ||
YAMAHA PLG-150AN | ✕ | ||
YAMAHA PLG-150DR/PC | ✕ | ||
YAMAHA PLG-150DX | ✕ | ||
YAMAHA PLG-150PF | ✕ | ||
YAMAHA PLG-100SG | ✓ | ||
YAMAHA PLG-150VL | ✓ | ||
YAMAHA TG300 | ✓ | ||
Roland GS | ✓ | ||
Roland SD | ✓ | ||
Roland C/M | ✓ | ||
KORG NS5R | ✓ | ||
KORG N1R | ✓ | Redirected to NS5R | |
KORG X5D(R) | ✓ | ||
KORG 05R/W | ✓ | ||
KAWAI GMega | ✓ | Also known as KAWAI K11 | |
AKAI SG01 | ✓ | ||
CASIO GZ-50M | ✓ | ||
ALESIS NanoSynth | ✕ | ||
System Common | Song position | ✕ | |
Song select | ✕ | ||
Tune | ✕ | ||
System RealTime | Clock | ✕ | No action defined |
Start | ✕ | No action defined | |
Continue | ✕ | No action defined | |
Stop | ✕ | No action defined | |
Aux messages | Local ON/OFF | ✕ | |
Active Sense | ✕ | No action defined |
SysEx Instructions
For a list of supported modes, refer to state.mjs
internal mode IDs.
Supported SysEx Instructions
- ✓: Supported
- -: Partially supported
- ✕: Not supported
- ?: Unknown
- (blank): N/A
Mutual instructions
GM | GM2 | MT-32 | XG | GS | 05R/W | X5D | NS5R | SD | GMega | GMega LX | SG-01 | GZ-50M | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
System reset | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ||||
Master setup | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✕ | ✓ | ✓ | ||||
Reverb setup | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |||||
Chorus setup | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |||||
Variation setup | ? | ✓ | ✓ | ||||||||||
Part setup | ? | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ||||
Equalizer | ✓ | ✓ | ✕ | ||||||||||
EFX / insertion | - | ✓³ | - | ✓ | |||||||||
Bitmap display¹ | ✓ | ✓ | ✓ | ||||||||||
Text display² | ✓ | ✓ | ✓ | ✓ | |||||||||
Drum setup | ? | ✓ | ✓ | ✓ | ✕ | ✕ | ✓ | ✕ | ✕ | ✕ |
- Support in GS is called "frame draw", and with multi-page support.
- Called "letter display" in XG, and "text insert" in GS.
- GS only has "delay" effect occupying the space of variation setup.
Device-specific instructions
Roland MT-32
- Temporary Patch Setup
Temporary Drum Setup- Temporary Timbre Setup
- Device Patch Setup
- Device Timbre Setup
- Patch Memory Write
- Timbre Memory Write
- System
Yamaha MU1000
A/D Part SetupA/D Mono/Stereo- System
Yamaha PLG-100SG
Master SetupPart Setup- PhoneSEQ Setup
Lyrics Information Setup
Yamaha PLG-150DX
Master SetupPart SetupDX Voice ParamDX Voice Additional Param
Yamaha PLG-150VL
Master SetupCurrent Voice Parameters- Part Setup
Roland SC-88
- Single/dual Mode
KORG X5D
- All Program Dump
- All Combi Dump
- Extended Multi Dump
KORG NS5R
- Mode Switch
- All Program Dump
- All Combi Dump
- Extended Multi Dump
Targets
Supported targets
General support table
The following list of targets have their support by Octavia status presented in a table. A target can be a model, a plugin board, a lineup, or a standard.
A supported standard may also have a list of specific target models listed.
For specific SysEx support range, refer to Supported SysEx Instructions. For a list of supported modes, refer to state.mjs
internal mode IDs.
Vendor | Target | Type | Bank | SysEx |
---|---|---|---|---|
MMA | GM | S | ✓ | ✓ |
MMA | GM2 | S | ✓ | ✓ |
Roland | MT-32 | S | ✓ | ✓ |
Roland | GS | S | ✓ | ✓ |
Roland | SD | S | ✓ | ✓ |
YAMAHA | TG | L | ✓ | ✓ |
YAMAHA | XG¹ | S | ✓ | ✓ |
YAMAHA | PLG-150AN | P | ✓ | - |
YAMAHA | PLG-150AP | P | ✓ | ✕ |
YAMAHA | PLG-150DR | P | ✓ | ✕ |
YAMAHA | PLG-150DX | P | ✓ | - |
YAMAHA | PLG-150PC | P | ✓ | ✕ |
YAMAHA | PLG-150PF | P | ✓ | ✕ |
YAMAHA | PLG-150VL | P | ✓ | ✓ |
YAMAHA | PLG-100SG | P | ✓ | ✓ |
YAMAHA | S90 ES | L | ✓ | ✓ |
YAMAHA | Motif ES | L | ✓ | ✓ |
KORG | AG-10 | M | ✓ | ✓ |
KORG | 05R/W | L | ✓ | ✓ |
KORG | X5DR | L | ✓ | ✓ |
KORG | NS5R/NX5R | L | ✓ | ✓ |
KAWAI | GMega | L | ✓ | ✓ |
KAWAI | GMega LX | M | ✓ | ✓ |
AKAI | SG01k | M | ✓ | ✓ |
CASIO | GZ-50M | M | ✓ | ✓ |
ALESIS | NanoSynth | M | ✕ | ✕ |
- Octavia implements XG level 3.0 or later, and XG version 2.0 or later.
Custom sound banks
- Voice name maps (
.mdat
) - SysEx bank dumps (
.syx
)- KORG X5 (05R/W)
- KORG X5D (X5DR)
- KORG NS5R (NX5R)
KORG TrinityYamaha PLG-AN (AN200)
- Yamaha S90 ES Voice Editor (
.s7e
) Yamaha Motif ES Voice Editor (.w7e
)- Korg Program/Combi/Global (
.pcg
)- Korg KROSS 2
Specific targets
Roland MT-32
Target | Type | Status |
---|---|---|
MT-32 | M | ✓ |
MT-100 | M | - |
CM-32L | M | ✓ |
CM-32LN | M | - |
CM-64 | M | - |
CM-500 | M | - |
LAPC-I | M | - |
LAPC-N | M | - |
RA-50 | M | - |
E-20 | M | - |
Roland GS
Target | Type | Status |
---|---|---|
CM-300 | M | ✓ |
SC-55 | L | ✓ |
SC-88 | L | ✓ |
SC-88 Pro | L | ✓ |
SC-8850 | L | ✓ |
SD-20 | M | ✓ |
SD-35 | M | ✓ |
SD-50 | M | ✓ |
SD-80 | M | ✓ |
SD-90 | M | ✓ |
SK-50 | L | - |
Yamaha TG
Target | Type | Status |
---|---|---|
TG55 | M | - |
TG33 | M | - |
TG77 | M | - |
TG100 | M | - |
TG500 | M | - |
TG300 | M | ✓ |
Yamaha XG
Target | Type | Status |
---|---|---|
DBXG50 | M | ✓ |
DBXG51 | M | ✓ |
DBXG60 | M | ✓ |
MU5 | M | ✓ |
MU80 | M | ✓ |
MU50 | M | ✓ |
MU90 | L | ✓ |
MU10 | M | ✓ |
MU100 | L | ✓ |
MU15 | M | ✓ |
MU128 | L | ✓ |
MU1000 | L | ✓ |
MU2000 | L | ✓ |
MU500 | M | ✓ |
PLG100-XG | P | ✓ |
QY700 | M | ✓ |
QY70 | M | ✓ |
QY100 | M | ✓ |
SW60XG | M | ✓ |
SW1000XG | M | ✓ |
S-YXG50 | M | ✓ |
S-YXG70 | M | ✓ |
S-YXG100 | M | ✓ |
S-YXG2006LE | M | ✓ |
Octavia standard visualizers
Octavia comes with a set of modular standard visualizers with each release.
For a guide on how to use the public demos, refer to demo visualizer usage.
Visualizers
Octavia Cambiare
- Lead developer: Lumière Élevé
The most feature-rich visualizer built on top of Octavia available. Inspired by MegaMID, vanBasco Karaoke Player and TiMidity++, Octavia Cambiare is designed from the ground up, and seeks to entirely replace what inspired it.
Octavia MU
- Lead developer: Lumière Élevé
A recreation of the screens on the Yamaha MU line up. Bitmap is collected with collective effort.
The font used for labels is Public Sans, licensed under SIL OFL.
Bitmap contributors
Special thanks to all of the people who had contributed the MU bitmap! If you see your name missing here, please contact us for proper credits.
- MIDIMan
- Lumière Élevé
- GFHK-SDGM
- MJG0117
Octavia SC
- Lead developer: Lumière Élevé
A recreation of the screens on Roland SC-55, Roland SC-88 and Roland SC-88 Pro.
The font used for labels is Work Sans, licensed under SIL OFL.
Octavia NS5R
- Lead developer: Lumière Élevé
A recreation of the screens on KORG NS5R, with help from JayB.
The font used for labels is Jost, licensed under SIL OFL.
Octavia QY
- Lead developer: Lumière Élevé
A recreation of the screens on the Yamaha QY line up, with help from JayB.
Octavia PSR
- Lead developer: GFHK-SDGM
A recreation of the screens on Yamaha PSR.
Octavia SC-8850
- Lead developer: Lumière Élevé
A recreation of the screen on Roland SC-8850.
Bitmap contributors
Special thanks to all of the people who had contributed the SC-8850 bitmap!
- SSQMinky
- MasteredRealm
- Thorndust
- GFHK-SDGM
- Lumière Élevé
Octavia MU15
- Lead developer: Lumière Élevé
A recreation of the screen on Yamaha MU15.
Support and specification table
MU | SC | NS5R | QY | PSR | SC-8850 | MU15 | Cambiare | TUI | |
---|---|---|---|---|---|---|---|---|---|
Max name length | 8 | 12 | 10² | 8 | 8 | 12 | 8 | 24 | 8 |
Max shown parts | 64 | 64 | 128 | 8 | 1 | 64 | 64 | 64 | 16 |
PC# start index | 1 | 1 | 1 | Both | 1 | 1 | 1 | 0 | N/A |
Voice details | PB | P | PB | PF | P | PB | P | PF | N |
Current mode | B | L | C | B | BL | D | B | CD | D |
Voice bitmap | ✓ | ✕ | ✕ | ✓ | ✓ | ✓ | ✕ | ✕ | ✕ |
Letter display | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Bitmap display | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Wider bitmap | ✕ | ✕ | ✓ | ✓ | ✕ | ✓ | ✕ | ✓ | ✕ |
Screen dump | ✕ | ✕ | ✓ | ✕ | ✕ | ✓ | ✕ | ✕ | ✕ |
Chord display¹ | ✕ | ✕ | ✕ | ✓ | ✓ | ✕ | ✕ | ✓ | ✕ |
Pixel blur | ✓³ | ✓ | ✓ | ✕ | ✓³ | ✓ | ✓³ | ✓ | ✕ |
Lyrics | ✕ | ✕ | ✕ | ✕ | ✓ | ✕ | ✕ | ✓ | ✓ |
Song title | ✕ | ✓ | ✕ | ✓ | ✓ | ✕ | ✕ | ✓ | ✓ |
Meta events | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✓ | ✓ |
Effect sends | ✓ | ✓ | ✓ | ✕ | ✕ | ✕ | ✕ | ✓ | ✓ |
Effect types | ✕ | ✕ | ✓ | ✕ | ✕ | ✕ | ✕ | ✓ | ✕ |
Switch part | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✕ |
PB/Transpose | ✓ | ✓ | ✓ | ✓ | ✕ | ✕ | ✕ | ✓ | ✓ |
Current position | ✕ | ✕ | ✕ | ✓ | ✓ | ✕ | ✕ | ✓ | ✓ |
VL monitor | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✓ | ✕ |
DX monitor | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✓ | ✕ |
User sound sets | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Custom MDAT | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✓ | ✕ |
Voice details
- N: Name only
- P: With program number
- B: With bank number
- F: With full bank numbers
Current mode
- B: Bitmap prompt
- L: Letter prompt
- C: Colour change
- D: Dedicated slot
Additional notes
- Planned feature, not yet implemented.
- Octavia NS5R can render voice names with at most 12 characters under certain conditions.
- Except for Octavia MU, Octavia PSR and Octavia MU15, the intensity of pixel blur is customizable.
state.mjs API
All constants and interfaces documented here are guaranteed to work, and very likely not subject to further changes.
Constants
MIDI modes
Octavia is compatible with a range of modes on MIDI synthesizers. A list of supported modes to their respective keys is available below.
?
: The default "nothing" mode. Octavia will try to detect the correct mode.gm
: General MIDI mode.gs
: Roland GS mode. GS is short for General Sound.xg
: Yamaha XG mode. Compatible with TG-100 and TG-300. XG is short for eXtended General.sc
: Roland GS mode, but with mode 1 or mode 2 set. Specific to Roland SoundCanvas SC-88 and up.g2
: General MIDI Level 2 mode.sd
: Roland SD mode. SD is used for Roland's Studio Canvas lineup.ns5r
: KORG NS5R mode. Compatible with NX5R, and has limited compatibility with KORG N1R and N5.x5d
: KORG X5D(R) mode. Compatible with AG-10.05rw
: KORG 05R/W and KORG X5 mode. Compatible with AG-10.k11
: Kawai GMega or K11 mode.sg
: Akai SG mode.krs
: KORG KROSS 2 mode.s90es
: Yamaha S90 ES mode.motif
: Yamaha Motif ES mode.mt32
: Roland MT-32 mode.doc
: Yamaha DOC mode. DOC is short for Disk Orchestra Collection.qy10
: Yamaha QY10 native mode.qy20
: Yamaha QY20 native mode.
MIDI event types
8
: Note off9
: Note on10
: Note aftertouch, a.k.a. polyphonic aftertouch11
: Channel controller change12
: Channel program change13
: Channel aftertouch14
: Channel pitch bend15
: System exclusive message
allocated
ccToPos
Interfaces
OctaviaDevice
General MIDI Extended
GME, short for General MIDI Extended, is a standard based off General MIDI level 1, which emphasizes on slightly extending the ability of General MIDI while not being too demanding. General MIDI Extended can be considered as a summarization of the common functionality among all GM-compatible synthesizers, and should be the baseline of all contemporary General MIDI-compatible synthesizers.
Requirements
Any GME-compliant synthesizer must adhere all requirements listed below.
- Has at least 24 oscillators available simultaneously (polyphony), which must either be...
- At least 24 fully dynamically allocated oscillators for both melodic and percussion sounds.
- At least 16 dynamically allocated oscillators for melodic sounds, 8 for percussion sounds.
- Supports all 16 MIDI channels, which...
- Can play arbitrary number of voices within the polyphony limit.
- Can change to a different instrument.
- Channel 10 is set to percussion by default.
- Correctly responds to listed required events, CC and RPN.
- Has all voices listed in the required voice list.
- Has drum kits following the required drum note mapping.
- Correctly responds to required System Exclusive messages.
Voice list
Drum voices
Drum kits will reside on MSB 124, and all level 1 kits will also reside on MSB 120.
The above portion is not yet decided.
PC# | Drum Kit Name | Level |
---|---|---|
000 | Standard Kit | 1 |
001 | Standard Kit 2 | 2 |
002 | Standard Kit 3 | 4 |
003 | Standard Kit L/R | 5 |
008 | Room Kit | 1 |
009 | Hip Hop Kit | 3 |
010 | Jungle Kit | 3 |
011 | Techno Kit | 4 |
012 | Dark Room Kit | 5 |
013 | House Kit | 4 |
014 | Techno Kit High | 4 |
015 | Techno Kit Low | 4 |
016 | Power Kit/Rock Kit | 1 |
017 | Rock Kit 2 | 3 |
018 | Rock Kit 3 | 4 |
019 | R&B Kit | 4 |
024 | Electro Kit | 1 |
025 | Analog Kit | 1 |
026 | Analog Kit 2 | 3 |
027 | Dance Kit | 3 |
028 | Rave Kit | 5 |
030 | Apogee Kit | 4 |
031 | Perigee Kit | 4 |
032 | Jazz Kit | 2 |
033 | Jazz Kit L/R | 5 |
040 | Brush Kit | 1 |
041 | Brush Kit 2 | 4 |
048 | Orchestra Kit | 1 |
049 | Ethnic Kit | 2 |
050 | Sakura Kit | 5 |
051 | China Kit | 5 |
052 | Asian Kit | 3 |
053 | Orchestra Kit Y | 5 |
054 | Gamelan Kit | 5 |
055 | Gamelan Kit 2 | 5 |
056 | SFX Kit | 2 |
057 | SFX Kit Y | 2 |
058 | SFX Kit Y 2 | 2 |
060 | SFX Kit 2 | 5 |
064 | Percussion Kit | 2 |
Melodic voices
Piano
PC# | Voice Name |
---|---|
000 | Grand Piano |
001 | Bright Grand Piano |
002 | Electric Grand Piano |
003 | Honky-tonk Piano |
004 | Electric Piano |
005 | Chorused Electric Piano |
006 | Harpsichord |
007 | Clavichord |
Chromatic percussion
PC# | Voice Name |
---|---|
008 | Celesta |
009 | Glockenspiel |
010 | Music Box |
011 | Vibraphone |
012 | Marimba |
013 | Xylophone |
014 | Tubular Bells |
015 | Dulcimer1 |
- Some implementations may swap
Dulcimer
out withSantur
.
Organ
PC# | Voice Name |
---|---|
016 | Drawbar Organ |
017 | Percussive Organ |
018 | Rock Organ |
019 | Church Organ |
020 | Reed Organ |
021 | French Accordion |
022 | Harmonica |
023 | Tango Accordion |
Guitar
PC# | Voice Name |
---|---|
024 | Nylon Acoustic Guitar |
025 | Steel Acoustic Guitar |
026 | Jazz Electric Guitar |
027 | Clean Electric Guitar |
028 | Muted Electric Guitar |
029 | Overdriven Guitar |
030 | Distortion Guitar |
031 | Guitar Harmonics |
Bass
PC# | Voice Name |
---|---|
032 | Acoustic Bass |
033 | Fingered Bass |
034 | Picked Bass |
035 | Fretless Bass |
036 | Slap Bass 1 |
037 | Slap Bass 2 |
038 | Synth Bass 1 |
039 | Synth Bass 2 |
Solo strings/orchestra
PC# | Voice Name |
---|---|
040 | Violin |
041 | Viola |
042 | Cello |
043 | Contrabass |
044 | Tremelo Strings |
045 | Pizzcato Strings |
046 | Harp |
047 | Timpani |
Ensemble strings/orchestra
PC# | Voice Name |
---|---|
048 | Ensemble Strings |
049 | Ensemble Slow Strings |
050 | Synth Strings 1 |
051 | Synth Strings 2 |
052 | Choir Aahs |
053 | Voice Oohs |
054 | Synth Voice |
055 | Orchestra Hit |
Brass
PC# | Voice Name |
---|---|
056 | Trumpet |
057 | Trombone |
058 | Tuba |
059 | Muted Trumpet |
060 | French Horn |
061 | Brass Section |
062 | Synth Brass 1 |
063 | Synth Brass 2 |
Reed
PC# | Voice Name |
---|---|
064 | Soprano Saxophone |
065 | Alto Saxophone |
066 | Tenor Saxophone |
067 | Baritine Saxophone |
068 | Oboe |
069 | English Horn |
070 | Bassoon |
071 | Clarinet |
Pipe
PC# | Voice Name |
---|---|
072 | Piccolo |
073 | Flute |
074 | Recorder |
075 | Pan Flute |
076 | Blown Bottle |
077 | Shakuhachi |
078 | Whistle |
079 | Ocarina |
Synth lead
PC# | Voice Name |
---|---|
080 | Square Wave Lead |
081 | Sawtooth Wave Lead |
082 | Synth Calliope Lead |
083 | Chiffer Lead |
084 | Charang Lead |
085 | Voice Lead |
086 | Fifth Sawtooth Lead |
087 | Bass & Lead |
Synth pad
PC# | Voice Name |
---|---|
088 | New Age Pad1 |
089 | Warm Pad |
090 | Poly Synth Pad |
091 | Choir Pad |
092 | Bowed Glass Pad |
093 | Metal Pad |
094 | Halo Pad |
095 | Sweep Pad |
- Or "Fantasia Pad".
Synth melodic sound effects
PC# | Voice Name |
---|---|
096 | Ice Rain |
097 | Soundtrack |
098 | Crystal |
099 | Atmosphere |
100 | Brightness |
101 | Goblins |
102 | Echo Drops |
103 | Sci-Fi |
Ethnic
PC# | Voice Name |
---|---|
104 | Sitar |
105 | Banjo |
106 | Shamisen |
107 | Koto |
108 | Kalimba |
109 | Bagpipe |
110 | Fiddle |
111 | Shanai |
Percussive
PC# | Voice Name |
---|---|
112 | Tinkle Bell |
113 | Agogo |
114 | Steel Drums |
115 | Woodblock |
116 | Taiko Drum |
117 | Melodic Tom |
118 | Synth Drum |
119 | Reverse Cymbal |
Sound effects
PC# | Voice Name |
---|---|
120 | Guitar Fret Noise |
121 | Breath Noise |
122 | Seashore |
123 | Bird Tweet |
124 | Telephone Ring |
125 | Helicopter |
126 | Applause1 |
127 | Gunshot |
- Can be optionally extended as a menu voice, with examples including
Stadium!!!
in KORG AI2 lineup.
Drum note mapping
- Regular: Required.
- Italic: Optional. If not defined, the note will behave the same as in Standard Kit.
- ←: Same as Standard Kit.
PC# | 0 | 1 | 8 | 16 | 24 | 25 | 32 | 40 | 48 | |
---|---|---|---|---|---|---|---|---|---|---|
Kit | Standard Kit | Standard 2 Kit | Room Kit | Power/Rock Kit | Electro Kit | Analog Kit | Jazz Kit | Brush Kit | Orchestra Kit | |
# | Note | |||||||||
35 | B~1 | Tight Kick | Tight Kick 2 | ← | Rock Tight Kick | Electro Tight Kick | Analog Tight Kick | Jazz Tight Kick | Jazz Tight Kick | Jazz Kick |
36 | C~2 | Kick | Kick 2 | Room Kick | Rock Kick | Electro Kick | Analog Kick | Jazz Kick | Brush Kick | Concert Bass Drum |
37 | C#2 | Side Stick | ← | ← | ← | ← | Analog Side Stick | ← | ← | ← |
38 | D~2 | Snare | Snare 2 | Room Snare | Rock Snare | Electro Snare | Analog Snare | Jazz Snare | Brush Tap | Concert Snare Drum |
39 | Eb2 | Hand Clap | ← | ← | ← | ← | ← | Jazz Hand Clap | Brush Slap | Castanet |
40 | E~2 | Tight Snare | Tight Snare 2 | Room Tight Snare | Rock Tight Snare | Electro Tight Snare | Analog Tight Snare | ← | Brush Swirl | Concert Snare Drum |
41 | F~2 | Floor Tom Lo | ← | Room Floor Tom Lo | Rock Floor Tom Lo | Electro Floor Tom Lo | Analog Floor Tom Lo | Jazz Floor Tom Lo | Brush Floor Tom Lo | Timpani F |
42 | F#2 | Hi-Hat Closed | Hi-Hat Closed 2 | Room Hi-Hat Closed | Room Hi-Hat Closed | Hi-Hat Closed 2 | Analog Hi-Hat Closed | Jazz Hi-Hat Closed | Brush Hi-Hat Closed | Timpani F# |
43 | G~2 | Floor Tom Hi | ← | Room Floor Tom Hi | Rock Floor Tom Hi | Electro Floor Tom Hi | Analog Floor Tom Hi | Jazz Floor Tom Hi | Brush Floor Tom Hi | Timpani G |
44 | Ab2 | Hi-Hat Pedal | Hi-Hat Pedal 2 | ← | ← | ← | Analog Hi-Hat Closed Hi | ← | Brush Hi-Hat Pedal | Timpani G# |
45 | A~2 | Low Tom | ← | Room Low Tom | Rock Low Tom | Electro Low Tom | Analog Low Tom | Jazz Low Tom | Brush Low Tom | Timpani A |
46 | Bb2 | Hi-Hat Open | Hi-Hat Open 2 | Room Hi-Hat Open | Room Hi-Hat Open | Hi-Hat Open 2 | Analog Hi-Hat Open | Jazz Hi-Hat Open | Brush Hi-Hat Open | Timpani A# |
47 | B~2 | Mid Tom Lo | ← | Room Mid Tom Lo | Rock Mid Tom Lo | Electro Mid Tom Lo | Analog Mid Tom Lo | Jazz Mid Tom Lo | Brush Mid Tom Lo | Timpani B |
48 | C~3 | Mid Tom Hi | ← | Room Mid Tom Hi | Rock Mid Tom Hi | Electro Mid Tom Hi | Analog Mid Tom Hi | Jazz Mid Tom Hi | Brush Mid Tom Hi | Timpani C |
49 | C#3 | Cymbal Crash 1 | ← | ← | ← | ← | Analog Cymbal Crash | ← | Brush Cymbal Crash | Timpani C# |
50 | D~3 | High Tom | ← | Room High Tom | Rock High Tom | Electro High Tom | Analog High Tom | Jazz High Tom | Brush High Tom | Timpani D |
51 | Eb3 | Cymbal Ride 1 | ← | ← | ← | ← | ← | ← | Brush Cymbal Ride | Timpani D# |
52 | E~3 | Chinese Cymbal | ← | ← | ← | Reverse Cymbal | ← | ← | ← | Timpani E |
53 | F~3 | Bell Ride | ← | ← | ← | ← | ← | ← | Brush Bell Ride | Timpani F 2 |
54 | F#3 | Tambourine | ← | ← | ← | ← | ← | ← | ← | ← |
55 | G~3 | Cymbal Splash | ← | ← | ← | ← | ← | ← | ← | ← |
56 | Ab3 | Cowbell | ← | ← | ← | ← | Analog Cowbell | ← | ← | ← |
57 | A~3 | Cymbal Crash 2 | ← | ← | ← | ← | ← | ← | ← | Concert Cymbal 2 |
58 | Bb3 | Vibraslap | ← | ← | ← | ← | ← | ← | ← | ← |
59 | B~3 | Cymbal Ride 2 | ← | ← | ← | ← | ← | ← | ← | Concert Cymbal |
60 | C~4 | Bongo Hi | ← | ← | ← | ← | ← | ← | ← | ← |
61 | C#4 | Bongo Lo | ← | ← | ← | ← | ← | ← | ← | ← |
62 | D~4 | Muted Conga Hi | ← | ← | ← | ← | Analog Conga Hi | ← | ← | ← |
63 | Eb4 | Open Conga Hi | ← | ← | ← | ← | Analog Conga Mid | ← | ← | ← |
64 | E~4 | Conga Lo | ← | ← | ← | ← | Analog Conga Lo | ← | ← | ← |
65 | F~4 | Timbale Hi | ← | ← | ← | ← | ← | ← | ← | ← |
66 | F#4 | Timbale Lo | ← | ← | ← | ← | ← | ← | ← | ← |
67 | G~4 | Agogo Hi | ← | ← | ← | ← | ← | ← | ← | ← |
68 | Ab4 | Agogo Lo | ← | ← | ← | ← | ← | ← | ← | ← |
69 | A~4 | Cabasa | ← | ← | ← | ← | ← | ← | ← | ← |
70 | Bb4 | Maracas | ← | ← | ← | ← | Analog Maracas | ← | ← | ← |
71 | B~4 | Short Whistle Hi | ← | ← | ← | ← | ← | ← | ← | ← |
72 | C~5 | Long Whistle Lo | ← | ← | ← | ← | ← | ← | ← | ← |
73 | C#5 | Short Guiro | ← | ← | ← | ← | ← | ← | ← | ← |
74 | D~5 | Long Guiro | ← | ← | ← | ← | ← | ← | ← | ← |
75 | Eb5 | Claves | ← | ← | ← | ← | Analog Claves | ← | ← | ← |
76 | E~5 | Woodblock Hi | ← | ← | ← | ← | ← | ← | ← | ← |
77 | F~5 | Woodblock Lo | ← | ← | ← | ← | ← | ← | ← | ← |
78 | F#5 | Muted Cuica | ← | ← | ← | ← | ← | ← | ← | ← |
79 | G~5 | Open Cuica | ← | ← | ← | ← | ← | ← | ← | ← |
80 | Ab5 | Muted Triangle | ← | ← | ← | ← | ← | ← | ← | ← |
81 | A~5 | Open Triangle | ← | ← | ← | ← | ← | ← | ← | ← |
82 | Bb5 | Shaker | ← | ← | ← | ← | ← | ← | ← | ← |
83 | B~5 | Jingle Bell | ← | ← | ← | ← | ← | ← | ← | ← |
84 | C~6 | Bell Tree | Bar Chimes | ← | ← | ← | ← | ← | ← | ← |
Events, CC and RPN
Events
Assembly
Except System Exclusive messages, the first byte of each MIDI event defines the event type and target channel. The first four bits define the event type, with the last four bits defining the target channel.
Types
ID# | ID | Type |
---|---|---|
8 | 0x8 | Note off |
9 | 0x9 | Note on |
10 | 0xa | Note aftertouch (PAT) |
11 | 0xb | Control change |
12 | 0xc | Program change |
13 | 0xd | Channel aftertouch (CAT) |
14 | 0xe | Pitch bend |
15 | 0xf | System messages |
System message types
ID# | ID | Type | Optional |
---|---|---|---|
240 | 0xf0 | System Exclusive (Start of Exclusive) | No |
247 | 0xf7 | System Exclusive (End of Exclusive) | No |
248 | 0xf8 | Clock | Yes |
250 | 0xfa | Start | Yes |
251 | 0xfb | Continue | Yes |
252 | 0xfc | Stop | Yes |
254 | 0xfe | Active sensing | Yes |
255 | 0xff | (Line invalid) Meta events | No |
Types
Control Changes
Mapping
Data
ID# | ID | Type | Range | Optional |
---|---|---|---|---|
0 | 0x00 | MSB Bank Select | 0-127 | No |
32 | 0x20 | LSB Bank Select | 0-127 | No |
6 | 0x06 | MSB Data Commit | 0-127 | No |
38 | 0x26 | LSB Data Commit | 0-127 | No |
98 | 0x62 | LSB NRPN | 0-127 | No |
99 | 0x63 | MSB NRPN | 0-127 | No |
100 | 0x64 | LSB RPN | 0-127 | No |
101 | 0x65 | MSB RPN | 0-127 | No |
96 | 0x60 | RPN Increase | 0-127 | No |
97 | 0x61 | RPN Decrease | 0-127 | No |
Voice
ID# | ID | Type | Range | Optional |
---|---|---|---|---|
1 | 0x01 | Modulation | 0-127 | No |
5 | 0x05 | Portamento Time | 0-127 | No |
7 | 0x07 | Volume | 0-127 | No |
10 | 0x0a | Pan | 0-127 | No |
11 | 0x0b | Expression | 0-127 | No |
64 | 0x40 | Sustain (Hold) | 0-127 | No |
65 | 0x41 | Portamento Switch | 0-127 | No |
66 | 0x42 | Sostenuto | 0-127 | No |
67 | 0x43 | Soft Pedal | 0-127 | No |
71 | 0x47 | Resonance | 0-127 | No |
72 | 0x48 | Release Time | 0-127 | No |
73 | 0x49 | Attack Time | 0-127 | No |
74 | 0x4a | Brightness | 0-127 | No |
75 | 0x4b | Decay Time | 0-127 | Yes |
76 | 0x4c | Vibrato Rate | 0-127 | Yes |
77 | 0x4d | Vibrato Depth | 0-127 | Yes |
78 | 0x4e | Vibrato Delay | 0-127 | Yes |
84 | 0x54 | Portamento Source | 0-127 | No |
91 | 0x5b | Effect (Reverb) | 0-127 | No |
92 | 0x5c | Effect (Tremelo) | 0-127 | Yes |
93 | 0x5d | Effect (Chorus) | 0-127 | No |
94 | 0x5e | Effect (Variation) | 0-127 | No |
95 | 0x5f | Effect (Phaser) | 0-127 | No |
Modes
ID# | ID | Type | Range | Optional |
---|---|---|---|---|
120 | 0x78 | All Sound Off | 0 | No |
121 | 0x79 | Reset All Controllers | 0 | No |
123 | 0x7b | All Note Off | 0 | No |
124 | 0x7c | Omni Off | 0 | Yes |
125 | 0x7d | Omni On | 0 | Yes |
126 | 0x7e | Mono | 0-16 | No |
127 | 0x7f | Poly | 0 | No |
Types
Registered Parameter Numbers
Non-registered Parameter Numbers
Warning
This section is optional.
System Exclusive
Painted Palette
Painted Palette is a headless bot implemented purely in JavaScript, which helps pixel placements on r/place. It is developed for the My Little Pony factions, but can work for any other faction with modification.
If the codebase isn't modified, in auto mode, Painted Palette runs on a defensive stance by default - as long as pixels covered by the template aren't badly damaged, it barely activates. If in manual mode, Painted Palette only places pixels when the user commands or schedules a pixel placement.
Features
- Extremely fast to build, fast and easy to deploy for anyone. IT prowness is not a problem.
- No dependency compiling before running.
- Fully-unattended automated updates.
- Relatively low on resources.
- Native support for multi-account deployments. (less than 10 per IP address)
Installation
Warning
Node.js on Windows does not respect proxy settings. If proxies are needed, switch to Deno instead.
With an acceptable Internet connection, the whole installation process should not take more than 20 seconds. On POSIX systems, the figure is even lower.
If you're up for the task, feel free to contribute, and expand our horizon of OS support!
Windows
- Download the latest version of
node_windows.zip
. - Extract
node_windows.zip
to an appropriate folder of your liking.
Linux, Android, macOS
- Ensure
bash
,curl
andunzip
are available. - Assign
export VARIANT=node
. - Make sure you have either Node.js 18 or Node.js 19 installed.
- Run
bash <(curl -Ls https://github.com/ltgcgo/painted-palette/raw/main/src/bash/install.sh)
.
Running
Warning
Despite our efforts on bot detection evasion, when not in manual mode, running the bot on your main is generally considered a bad idea. Please use disposable alts when in auto mode.
For more advanced usage, please refer to command line docs.
Windows (default GUI only)
- Double-click
webui.cmd
, and click on the link it provides. Should point to 127.0.0.1:14514 by default.- If the browser displays an error page, run
winFix.cmd
first, then restartgui.cmd
to see if the problem goes away.
- If the browser displays an error page, run
Linux, Android, macOS
- Run
./palette-bot batch
, and click on the link it provides. - Do you have Tor installed on your system? If yes and you're using Deno, run
./palette-tor batch
to use it without the tedious configuration process! - Are you running Painted Palette with Deno on Linux? If yes, run
./palette-proxy batch
to connect to public proxy pools with ease!
Windows (CLI)
- Open a terminal session where
webui.cmd
is located. - Run with
.\node.exe node.js <arguments>
.
Podman/Docker
- Clone the repo via
git clone https://github.com/ltgcgo/painted-palette.git palette
. - Switch into
oci
viacd ./palette/oci
. - Run
docker-compose up -d
if on Docker, orpodman-compose up -d
if on Podman.
Open Source
Painted Palette is a piece of open-source software, licensed under GNU GPL 3.0.
Source code: GitHub
Web UI
WIP
Command line
The Windows build does not ship with a helper like ./palette-bot
. As such, please replace ./palette-bot
with node node.js
or deno run --allow-read --allow-write --allow-net deno.js
.
With Deno or Bun, if you need to specify custom proxies, define the https_proxy
environment variable (e.g. https_proxy=http://127.0.0.1:4444/
). There are direct proxy integrations available on Linux and Android, which can be used by replacing ./palette-bot
with either ./palette-proxy
for public proxy pools, or ./palette-tor
for Tor.
Environment variables
BIND_ADDRESS
: Define a bind address. Do not include ports.HTTP_PROXY
: Used by Deno and Bun to connect to upstream proxies.HTTPS_PROXY
: Same as above. Must be the same asHTTP_PROXY
.NO_UPDATE
: Set to1
to disable the automatic updater.PORT
: Set the port PP listens for REST API calls. Used in./palette-bot ctl
.SLEEP
: Set to1
to behave as if./palette-bot ctl sleep
is run.TEMPLATE_URL
: Customize the pointer URL.
./palette-bot help
Prints help messages.
./palette-bot paint
Deprecated and not recommended. Paint on Reddit with given credentials.
Format: ./palette-bot paint <username> <password> <otp>
Examples:
- Direct login:
./palette-bot paint myCoolName myGoodPassword
- Direct login with 2FA codes:
./palette-bot paint myCoolName myGoodPassword 114514
./palette-bot pixel
Removed. Paint on VKontakte with given credentials.
Same format as ./palette-bot paint
.
./palette-bot test
Deprecated and not recommended. Paint on the test server with given credentials.
Same format as ./palette-bot paint
.
./palette-bot batch
Start a batch mode server for account management, complete with Web UI and REST API.
Since version 0.0.16, manual mode became the default - pixel placements require user interaction, and only a single account is allowed.
Format: ./palette-bot batch <port>
./palette-bot ctl
Send commands to a running batch server. Define the target port which the batch server listens on with the environment variable PORT
.
Format: ./palette-bot ctl <subcommand> <...args>
Subcommands
r/place 2023
Warning
Information on this page is outdated.
Written on 22nd June 2023
Warning
r/place 2023 did not happen on 1st April or 23rd June.
You know the drill: r/place 2023 is coming. So we prepared a list of FAQs, for you as a brony/pegasister to bootstrap your knowledge!
What is r/place?
r/place is a social experiment run by Reddit, where every participant gets to place coloured pixels with a defined cooldown. With itself categorized as a form of "pixel battle", it is by far the largest pixel battle held across the globe.
With only the power of a single person, not much could be created. However, with the power of factions, there's no such thing as "impossible"!
Why should I participate?
Although r/place isn't an annual event, Reddit held r/place last year (2022) also. And last year, we suffered dozens of raids, most of them lost due to a lack of firepower, and were able to recover solely because attackers went inactive eventually, either due to sleeping or due to recess between raids. We hope we could stop the same from happening again.
We prepared for r/place in advance this year, but with multi-account and automated pixel placement banned in the main faction, all while protests regarding Reddit APIs going in full swing, the expected firepower looks even dimmer. Despite the ongoing Reddit API fiasco, we desperately need everyone we can hopefully get, to extend our firepower as much as possible for all possible defense. Please consider participating the event!
When is it expected to happen?
On 23rd June 2023, Reddit's anniversary before its IPO. The exact time may vary, but it is rumored to happen at around 13:00 UTC.
How do I participate as a My Little Pony fan?
Lucky for us, a group of enthusiastic bronies established a faction before r/place even began, which became the main MLP faction of r/place 2023. But unlucky for us, said faction recently got splintered.
Why the splinter?
The initial trigger was an announcement on 18th June, regarding ban on all forms of automatic pixel placement, alongwith joining an unknown alliance called "P3ACE".
The ban alone did directly result in the creation of a faction, but it was a series of indications and later dealings sending the splinter onto a seemingly irreversible course: lack of transparency regarding joining the alliance, single parties meddling and forced the join, reluctance of communication regarding multi-account and automated pixel placement, with certain mods outright shunning and diverting arguments, all while removing downvotes on that specific announcement. All these enraged some parties, setting the splinter in stone.
The current splinter does not dwindle the firepower MLP as a whole possesses, as both use the very same template.
What about the pros and cons of automated pixel placements?
Pros
- Relatively low resource consumption, good for low-end devices
- Does not require you to stare at a screen and clicking your mouse for hours end
- Does not hinder you from your work
- Allows you to sleep as usual
Cons
- If only with automated placements, one cannot experience the event to its fullest
- Shamed by some people
- "Does not believe in friendship"
How do existing implementations of automation fit?
- Browser overlay: Auto-clicker is removed, and tab freeze circumvention became borked. Auto-focus and automatic colour picking still exist, but every pixel placement now requires user interactions.
- PonyPixel (Python headless): Retired.
- Painted Palette (JavaScript headless): A seperate manual-only mode is planned, but is largely unhindered.
How should I join the factions?
With the main faction prohibited discussions regarding several topics, the splintered-off faction offers a supplemental and more libre place where said topics are likely not forbidden. If you are fine with all the bureaucracy issues in the main faction, and agrees to stare at a screen for hours to place every single pixel manually, you can join the main faction. Otherwise, joining the splintered-off faction is much recommended.
Invite links
Since Painted Palette by itself is a somewhat independent project, it has an additional place for dev talks unrelated to the splinter.
- Secret r/place Brownies (the splintered-off faction): https://discord.gg/Nhf8HrWAku
- Sky Splash's Island: https://discord.gg/ZnU6sgDT
- Independent Painted Palette dev talks: Discord topic
- Main faction:
https://discord.gg/BronyPlace
raven
💨 Lightning-fast intuitive typing.
Target scripts
Usage
m17n
m17n
is an IME library for mapped stream conversion of characters. To develop schemas for m17n
, read the database tutorial.
m17n
is included in both IBus (Intelligent Input Bus) and fcitx5
.
Linux
- Get the required
.mim
files. - Check if the IME framework of your system supports
m17n
. Most Linux desktop distros with IBus hasm17n
support included by default. - Check if directory
~/.m17n.d/
exists for the current user. If not, create it viamkdir ~/.m17n.d/
. - Copy the
.mim
files you want to use to~/.m17n.d
. - Restart your IME framework.
- If on IBus, run
ibus restart
.
- If on IBus, run
Android
Warning
No input methods on Android support
m17n
currently. For its possible support on Android, please check out the issue in thefcitx5-android
project.
Rime
Rime is an IME framework for implementing custom input schemas for different languages. To develop schemas for Rime, read here (machine translation required).
Rime is supported on Linux via IBus, Windows and macOS. Platform support is extended with forks, e.g. for fcitx5 (fcitx-rime
), Android (Trime) and iOS (Hamster, iRime).
The official Rime documentation is only available in Orthodox Chinese.
Linux
- Get the required
.yaml
files. Check for files ending in.schema.yaml
,.dict.yaml
and.custom.yaml
. - Copy the
.yaml
files to~/.config/ibus/rime/
. - (Optional) Customize the new schema as you see fit.
- Enable the new schema in
~/.config/ibus/rime/default.custom.yaml
. - Redeploy Rime via
touch ~/.config/ibus/rime/; ibus restart
.
Windows
- Get the required
.yaml
files. Check for files ending in.schema.yaml
,.dict.yaml
and.custom.yaml
. - Copy the
.yaml
files to%APPDATA%\\Rime
. - (Optional) Customize the new schema as you see fit.
- Enable the new schema in
%APPDATA%\\Rime\\default.custom.yaml
. - Redeploy Rime via start menu or right-click menu of the taskbar icon.
Android
fcitx5-android
TBD.
Trime
TBD.
Key map
Consonants
Keymap | AR | UR/FA | UG |
---|---|---|---|
a | ا (a) | ا (a) | ا (a) |
b | ب (b) | ب (b) | ب (b) |
p | پ (p) | پ (p) | |
t | ت (t) | ت (t) | ت (t) |
T | ٹ (ṭ) | ||
C | ث (ṯ) | ث (s) | |
j | ج (j) | ج (j) | ج (j) |
c | چ (c) | چ (ch) | |
h | ح (ḥ) | ح (h) | |
K | خ (ḫ) | خ (x) | خ (x) |
d | د (d) | د (d) | د (d) |
D | ڈ (ḍ) | ||
Z | ذ (ḏ) | ذ (z) | |
r | ر (r) | ر (r) | ر (r) |
R | ڑ (ṛ) | ||
z | ز (z) | ز (z) | ز (z) |
X | ژ (zh) | ژ (zh) | |
s | س (s) | س (s) | س (s) |
x | ش (š) | ش (ś) | ش (sh) |
S | ص (ṣ) | ص (s) | |
J | ض (ḍ) | ض (z) | |
v | ط (ṭ) | ط (t) | |
V | ظ (ẓ) | ظ (z) | |
e | ع (ʿ) | ع (') | |
G | غ (ġ) | غ (ġ) | غ (gh) |
f | ف (f) | ف (f) | ف (f) |
q | ق (q) | ق (q) | ق (q) |
k | ك (k) | ک (k) | ك (k) |
g | گ (g) | گ (g) | |
l | ل (l) | ل (l) | ل (l) |
m | م (m) | م (m) | م (m) |
n | ن (n) | ن (n) | ن (n) |
N | ں (◌̃) | ڭ (ng) | |
o | ه (h) | ه (FA), ہ (UR) (h) | ھ (h) |
w | و (w) | و (w/ū) | ۋ (w) |
H | ھ (-h) | ||
u | ء (ʾ) | ء (') | ئ |
i | ي (y) | ی (y/ī) | ي (y) |
y | ے (ē) | ە (e) | |
ى (ā) | |||
و (o) | |||
ۇ (u) | |||
ۆ (ö) | |||
ۈ (ü) | |||
ې (ë) | |||
ى (i) |
Vowels
Letters with hamza
Keymap | AR | UR/FA | UG |
---|---|---|---|
A | آ (ā) | آ (ā) | |
أ (ʾa/ʾu) | |||
إ (ʾi) | |||
ؤ | |||
ࢨ |
Numbers
Arabic and Persian numerals have separate codepoints, despite only three of them (4, 5, 6) look different. Urdu numerals share the same codpoint as the Persian ones, but three of them (4, 6, 7) should look different with proper language settings.
Keymap | AR | UR/FA | UG |
---|---|---|---|
0 | ٠ | ۰ | ٠ |
1 | ١ | ۱ | ١ |
2 | ٢ | ۲ | ٢ |
3 | ٣ | ۳ | ٣ |
4 | ٤ | ۴ | ٤ |
5 | ٥ | ۵ | ٥ |
6 | ٦ | ۶ | ٦ |
7 | ٧ | ۷ | ٧ |
8 | ٨ | ۸ | ٨ |
9 | ٩ | ۹ | ٩ |
Punctuations
Chinese Bopomofo
A non-Latin transliteration system for Standard Chinese and other Sinitic languages.
Key map
Keys are mainly ordered via native Bopomofo ordering. Spaces are used for stream breaking.
Consonants
Standard
Sequence | Bopomofo | Pinyin | Generic | Symbols II | Wade-Giles | Postal¹ |
---|---|---|---|---|---|---|
b | ㄅ | b | b | b | p | p |
p | ㄆ | p | p | p | pʻ | pʻ |
m | ㄇ | m | m | m | m | m |
f | 匚 | f | f | f | f | f |
d | ㄉ | d | d | d | t | t |
t | ㄊ | t | t | t | tʻ | tʻ |
n | ㄋ | n | n | n | n | n |
l | ㄌ | l | l | l | l | l |
g | ㄍ | g | g | g | k | k |
k | ㄎ | k | k | k | kʻ | kʻ |
h | ㄏ | h | h | h | h | h |
j | ㄐ | j | ji | ji | chi | tsi; ki |
q | ㄑ | q | ci | chi | chʻi | tsʻi; kʻi |
x | ㄒ | x | si | shi | hsi | si; hi |
Z | ㄓ | zh | jh | j | ch | ch |
C | ㄔ | ch | ch | ch | chʻ | chʻ |
S | ㄕ | sh | sh | sh | sh | sh |
r | ㄖ | r | r | r | j | j |
z | ㄗ | z | z | tz | ts | ts |
c | ㄘ | c | c | ts | tsʻ | tsʻ |
s | ㄙ | s | s | s | s | s |
i | ㄧ | y | y | y | y | y |
I | 丨 | y | y | y | y | y |
u | ㄨ | w | w | w | w | w |
U | ㄩ | yu | yu | yu | yu | yu |
v | ㄪ | v | - | - | v | v |
N | ㄫ | ng | - | - | ng | ng |
G | ㄬ | gn | - | - | gn | gn |
mm | ㆬ | - | - | - | m | m |
nn | ㄯ | n | n | n | n | n |
NN | ㆭ | ng | ng | ng | ng | ng |
- Aspirations have been added to better distinguish between consonants.
Extension
Sequence | Bopomofo |
---|---|
B | ㆠ |
V | (non-Unicode) |
D | (non-Unicode) |
L | ㆹ |
G | ㆣ |
H | ㆸ |
Q | ㆼ |
K | ㆽ |
R | (non-Unicode) |
N/A | (non-Unicode) |
J | ㆢ |
X | (non-Unicode) |
N/A | (non-Unicode) |
N/A | ㆡ |
N/A | (non-Unicode) |
Vowels
Standard
Sequence | Bopomofo | Pinyin | Generic | Symbols II | Wade-Giles | Postal |
---|---|---|---|---|---|---|
a | ㄚ | a | a | a | a | a |
o | ㄛ | o | o | o | o | o |
e | ㄜ | e | e | e | o/ê/eh | e |
eh | ㄝ | ê | e | e | eh | eh |
i | ㄧ | i | i | i | i | i |
I | 丨 | i | i | i | i | i |
u | ㄨ | u | u | u | u | u/uh |
U | ㄩ | ü | yu | iu | ü | ü |
ih | ㄭ | i | ih | r | ih/ŭ | ih/ŭ |
uh | ㆨ | i | ih | r | ih/ŭ | ih/ŭ |
ai | ㄞ | ai | ai | ai | ai | ai |
ei | ㄟ | ei | ei | ei | ei | ei |
ui uei | ㄨㄟ | ui | uei | uei | ui/uei | wei |
ao au | ㄠ | ao | ao | au | ao | ao |
ou | ㄡ | ou | ou | ou | ou | ow |
iu iou | ㄧㄡ | iu | iou | iou | iu | iu |
Iu Iou | 丨ㄡ | iu | iou | iou | iu | iu |
an | ㄢ | an | an | an | an | an |
en | ㄣ | en | en | en | en | en |
in ien | ㄧㄣ | in | in | in | in | in |
In Ien | 丨ㄣ | in | in | in | in | in |
un uen | ㄨㄣ | un | un | uen | un | un |
Un Uen | ㄩㄣ | ün | yun | iun | ün | ün |
aN | ㄤ | ang | ang | ang | ang | ang |
eN | ㄥ | eng | eng | eng | êng | êng |
iN ieN | ㄧㄥ | ing | ing | ing | ing | ing |
IN IeN | 丨ㄥ | ing | ing | ing | ing | ing |
oN uN ueN | ㄨㄥ | ong | ong | ung | ung | ung |
UN UeN | ㄩㄥ | iong | yong | iung | iung | iung |
ie ieh | ㄧㄝ | ie | ie | ie | ieh | ieh |
Ie Ieh | 丨ㄝ | ie | ie | ie | ieh | ieh |
Ue Ueh | ㄩㄝ | üe | yue | iue | üeh | üeh |
er | ㄦ | er | er | er | êrh | êrh |
Additional combinations
Bopomofo | Pinyin | Generic | Symbols II | Wade-Giles | Postal |
---|---|---|---|---|---|
ㄧㄚ | ia | ia | ia | ia | ia |
ㄨㄚ | ua | ua | ua | ua | wa |
ㄨㄛ | uo | uo | uo | uo | wo |
ㄨㄞ | uai | uai | uai | uai | wai |
ㄧㄠ | iao | iao | iau | iao | iao |
ㄧㄢ | ian | ian | ian | ien | ien |
ㄨㄢ | uan | uan | uan | uan | wan |
ㄩㄢ | üan | yuan | iuan | üan | üan |
ㄧㄤ | iang | iang | iang | iang | iang |
ㄨㄤ | uang | uang | uang | uang | wang |
Extension
Sequence | Bopomofo |
---|---|
N/A | ㆩ |
A | ㆿ |
O | ㆦ |
On | ㆧ |
N/A | (non-Unicode) |
N/A | (non-Unicode) |
N/A | ㆤ |
N/A | ㆥ |
E | ㆾ |
N/A | (non-Unicode) |
N/A | ㆪ |
N/A | ㆫ |
N/A | ㆮ |
N/A | ㆯ |
N/A | ㆰ |
N/A | ㆱ |
on | (non-Unicode) |
N/A | ㆲ |
Tailing
Sequence | Bopomofo |
---|---|
W | ㆷ |
Wb | ㆴ |
Wd | ㆵ |
Wg | ㆻ |
W1 | ˉ |
W2 | ˊ |
W3 | ˇ |
W4 | ˋ |
W5 | ˙ |
W6 | ˪ |
W7 | ˫ |
Cyrillic script
English phonetic alphabets
As per effort of decreasing the learning curve as much as possible, all English phonetical alphabets share the same set of key map.
Included alphabets
British English Phonetic Alphabet
BEPA is an adaptation of International Phonetic Alphabet, optimized to represent the sounds of British English, and by extension all of its variants.
Shavian alphabet
The Shavian alphabet is a constructed alphabet aims to permit efficient writing and spelling for British English Received Pronunciation.
Deseret alphabet
Warning
Due to a lack of several vowels, there are no plans to support the Deseret alphabet as of yet.
The Deseret alphabet is a constructed alphabet developed to be used in an English-language spelling reform for American English.
Key map
Keys are ordered via BEPA.
Vowels
Vowels require at most two keys.
Short vowels
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
A | æ | 𐑨 | 𐐰 | cat |
e eh | ɛ | 𐑧 | 𐐯 | bet |
Ee EE | e | 𐑧 | 𐐯 | bet |
i ih | ɪ | 𐑦 | 𐐮 | fit |
o oh | ɒ | 𐑪 | 𐐱 | hot |
a ah | ʌ | 𐑳 | 𐐲 | cut |
u uh | ʊ | 𐑫 | 𐐳 | cook |
E Eh | ə | 𐑩 | 𐐲 | lover |
I | i | 𐑦 | 𐐨 | unity |
U | u | 𐑫 | 𐐭 |
Long vowels
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
ii | iː | 𐑰 | 𐐨 | eat |
oo | ɔː | 𐑷 | 𐐫 | all |
ee | ɜː | 𐑻 | 𐐲𐑉 | her |
uu | uː | 𐑵 | 𐐭 | who |
aa | ɑː | 𐑭 | 𐐪 | car |
Diphthongs
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
ei | eɪ | 𐑱 | 𐐩 | cake |
ai | aɪ | 𐑲 | 𐐴 | like |
oi | ɔɪ | 𐑶 | 𐑎 | oil |
eu | əʊ | 𐑴 | 𐐬 | coat |
ou | oʊ | 𐑴 | 𐐬 | hope |
au | aʊ | 𐑬 | 𐐵 | how |
ir | ɪə | 𐑾 | 𐐮𐐲 | ear |
er | ɛə | 𐑺 | 𐐯𐑉 | air |
ur | ʊə | 𐑫𐑩 | 𐐳𐐲 | sure |
Shavian compatibles
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
aR | ɑːr | 𐑸 | 𐐪𐑉 | art |
oR | ɔːr | 𐑹 | 𐐫𐑉/𐐬𐑉 | ore |
eR | ɛər | 𐑺 | 𐐯𐑉 | air |
Er | ər | 𐑼 | 𐐲𐑉 | lover |
ER | ɜːr | 𐑻 | 𐐲𐑉 | hurt |
iR | ɪər | 𐑽 | 𐐮𐐲𐑉 | ear |
yU | juː | 𐑿 | 𐑏 | you |
Consonants
None of the consonants require two keys.
Voiceless-voiced pairs
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
p | p | 𐑐 | 𐐹 | pat |
b | b | 𐑚 | 𐐺 | bat |
t | t | 𐑑 | 𐐻 | tie |
d | d | 𐑛 | 𐐼 | deer |
k | k | 𐑒 | 𐐿 | cat |
g | g | 𐑜 | 𐑀 | get |
s | s | 𐑕 | 𐑅 | sit |
z | z | 𐑟 | 𐑆 | zip |
f | f | 𐑓 | 𐑁 | fit |
v | v | 𐑝 | 𐑂 | van |
T | θ | 𐑔 | 𐑃 | thank |
D | ð | 𐑞 | 𐑄 | mother |
S | ʃ | 𐑖 | 𐑇 | shell |
Z | ʒ | 𐑠 | 𐑈 | vision |
C | tʃ | 𐑗 | 𐐽 | chips |
j | dʒ | 𐑡 | 𐐾 | juice |
q | tr | 𐑑𐑮 | 𐐻𐑉 | try |
Q | dr | 𐑛𐑮 | 𐐼𐑉 | dry |
c | ts | 𐑑𐑕 | 𐐻𐑅 | hats |
J | dz | 𐑛𐑟 | 𐐼𐑆 | hands |
Aspirated, nasal and etc
Sequence | BEPA | Shavian | Deseret | Example |
---|---|---|---|---|
h | h | 𐑣 | 𐐸 | hat |
H | x | 𐑣 | 𐐸 | loch |
m | m | 𐑥 | 𐑋 | mad |
n | n | 𐑯 | 𐑌 | nod |
N | ŋ | 𐑙 | 𐑍 | ring |
l | l | 𐑤 | 𐑊 | luck |
r | r | 𐑮 | 𐑉 | ring |
y | j | 𐑘 | 𐐷 | you |
w | w | 𐑢 | 𐐶 | way |
Specials
These characters will only be present in their respective alphabets, and will be null-routed in others.
Sequence | BEPA | Shavian | Deseret | Description |
---|---|---|---|---|
x | ˈ | N/A | N/A | Primary stress in BEPA/IPA. |
X | ˌ | N/A | N/A | Secondary stress in BEPA/IPA. |
ax ex ix ox ux | N/A | · | N/A | Naming dot in Shavian. |
Merged key map
Some letters in traditional Mongolian may have multiple codepoints and mappings, this is reserved for different pronunciations of the identical-looking letters.
Vowels
Keymap | IPA | Mongolian | Manchu | Sibe | Todo |
---|---|---|---|---|---|
a | ɑ | ᠠ | ᠠ | ᠠ | ᠠ |
e | ə | ᠡ | ᡝ | ᡝ | ᡄ |
i | i | ᠢ | ᡳ | ᡞ | ᡅ |
o | ɔ | ᠣ | ᠣ | ᠣ | ᡆ |
u | ʊ | ᠤ | ᡠ | ᡠ | ᡇ |
O | o | ᠥ | ᡈ | ||
U | u | ᠦ | ᡡ | ᡡ | ᡉ |
E | e | ᠧ | |||
I | ɨ | ᡟ | ᡟ | ||
`` | ː | ᡃ |
Consonants
Keymap | IPA | Mongolian | Manchu | Sibe | Todo |
---|---|---|---|---|---|
n | n | ᠨ | ᠨ | ᠨ | ᠨ |
N | ŋ | ᠩ | ᠩ | ᡢ | ᡊ |
b | b | ᠪ | ᠪ | ᠪ | ᡋ |
p | p | ᠫ | ᡦ | ᡦ | ᡌ |
h | x | ᠬ | ᡥ | ᡥ | ᡍ |
g | g | ᠭ | ᡤ | ᡤ | ᡎ |
m | m | ᠮ | ᠮ | ᠮ | ᡏ |
l | l | ᠯ | ᠯ | ᠯ | ᠯ |
s | s | ᠰ | ᠰ | ᠰ | ᠰ |
S | ʃ | ᠱ | ᡧ | ᡧ | ᠱ |
t | t | ᠲ | ᡩ | ᡩ | ᡐ |
d | d | ᠳ | ᡨ | ᡨ | ᡑ |
c | t͡ʃ (t͡s) | ᠴ | ᠴ | ᠴ | ᡒ |
j | d͡ʒ (d͡z) | ᠵ | ᠵ | ᡪ | ᡓ |
y | j | ᠶ | ᠶ | ᠶ | ᡕ |
r | r | ᠷ | ᡵ | ᠷ | ᠷ |
w | w | ᠸ | ᠸ | ᠸ | ᡖ |
f | f | ᠹ | ᡶ | ᡫ | ᠸ |
k | k | ᠺ | ᡴ | ᡣ | ᠺ |
K | k | ᠻ | ᠺ | ᠺ | |
G | k | ᡬ | ᡬ | ||
H | k | ᡭ | ᡭ | ||
C | t͡s | ᠼ | ᡮ | ᡮ | ᡔ |
J | d͡z | ᠽ | ᡯ | ᡯ | ᠴ |
x | x | ᠾ | ᡙ | ||
R | ʐ | ᠿ | ᡰ | ᡰ | |
L | ɬ | ᡀ | |||
Z | d͡ʐ | ᡁ | ᡷ | ᡲ | |
T | t͡ʂ | ᡂ | ᡱ | ᡱ |
Split key map
Mongolian
Vowels
U+ | Keymap | IPA | Mongolian |
---|---|---|---|
1820 | a | ɑ | ᠠ |
1821 | e | ə | ᠡ |
1822 | i | i | ᠢ |
1823 | o | ɔ | ᠣ |
1824 | u | ʊ | ᠤ |
1825 | O | o | ᠥ |
1826 | U | u | ᠦ |
1827 | E | e | ᠧ |
Consonants
U+ | Keymap | IPA | Mongolian |
---|---|---|---|
1828 | n | n | ᠨ |
1829 | N | ŋ | ᠩ |
182A | b | b | ᠪ |
182B | p | p | ᠫ |
182C | h | x | ᠬ |
182D | g | g | ᠭ |
182E | m | m | ᠮ |
182F | l | l | ᠯ |
1830 | s | s | ᠰ |
1831 | S | ʃ | ᠱ |
1832 | t | t | ᠲ |
1833 | d | d | ᠳ |
1834 | c | t͡ʃ / t͡s | ᠴ |
1835 | j | d͡ʒ / d͡z | ᠵ |
1836 | y | j | ᠶ |
1837 | r | r | ᠷ |
1838 | w | w | ᠸ |
1839 | f | f | ᠹ |
183A | k | k | ᠺ |
183B | K | k | ᠻ |
183C | C | t͡s | ᠼ |
183D | J | d͡z | ᠽ |
183E | x | x | ᠾ |
183F | R | ʐ | ᠿ |
1840 | L | ɬ | ᡀ |
1841 | Z | d͡ʐ | ᡁ |
1842 | T | t͡ʂ | ᡂ |
Manchu and Sibe
Seven letters in Sibe are different from Manchu, namely i, ŋ, k, f, j, zh and r. Be careful of the codepoints used in Sibe texts.
Vowels
U+ | Keymap | IPA | Manchu & Sibe |
---|---|---|---|
1820 | a | ɑ | ᠠ |
185D | e | ə | ᡝ |
1873 / 185E | i | i | ᡳ / ᡞ |
1823 | o | ɔ | ᠣ |
1860 | u | u | ᡠ |
1861 | U | ʊ | ᡡ |
185F | I | ɨ | ᡟ |
Consonants
U+ | Keymap | IPA | Manchu & Sibe |
---|---|---|---|
1828 | n | n | ᠨ |
1829 / 1862 | N | ŋ | ᠩ / ᡢ |
1874 / 1863 | k | k | ᡴ / ᡣ |
1864 | g | g | ᡤ |
1865 | h | x | ᡥ |
182A | b | b | ᠪ |
1866 | p | p | ᡦ |
1830 | s | s | ᠰ |
1867 | S | ʃ | ᡧ |
1868 | t | t | ᡩ |
1869 | d | d | ᡨ |
182F | l | l | ᠯ |
182E | m | m | ᠮ |
1834 | c | t͡ʃ | ᠴ |
1835 / 186A | j | d͡ʒ | ᠵ / ᡪ |
1836 | y | j | ᠶ |
183A | K | k | ᠺ |
186C | G | g | ᡬ |
186D | H | x | ᡭ |
1875 / 1837 | r | r | ᡵ / ᠷ |
1876 / 186B | f | f | ᡶ / ᡫ |
1838 | w | w | ᠸ |
186E | C | t͡s | ᡮ |
186F | J | d͡z | ᡯ |
1870 | R | ʐ | ᡰ |
1871 | T | t͡ʂ | ᡱ |
1877 / 1872 | Z | d͡ʐ | ᡷ / ᡲ |
Todo
Vowels
U+ | Keymap | IPA | Todo |
---|---|---|---|
1820 | a | ɑ | ᠠ |
1844 | e | ə | ᡄ |
1845 | i | i | ᡅ |
1846 | o | ɔ | ᡆ |
1847 | u | ʊ | ᡇ |
1848 | O | o | ᡈ |
1849 | U | u | ᡉ |
1843 | `` | ː | ᡃ |
Consonants
U+ | Keymap | IPA | Todo |
---|---|---|---|
1828 | n | n | ᠨ |
184A | N | ŋ | ᡊ |
184B | b | b | ᡋ |
184C | p | p | ᡌ |
184D | h | x | ᡍ |
184E | g | g | ᡎ |
184F | m | m | ᡏ |
182F | l | l | ᠯ |
1830 | s | s | ᠰ |
1831 | S | ʃ | ᠱ |
1850 | t | t | ᡐ |
1851 | d | d | ᡑ |
1852 | c | t͡ʃ | ᡒ |
1834 | `` | ᠴ | |
1853 | j | d͡ʒ | ᡓ |
1855 | y | j | ᡕ |
1837 | r | r | ᠷ |
1856 | w | w | ᡖ |
1838 | f | f | ᠸ |
1857 | G | g | ᡗ |
1858 | k | k | ᡘ |
1854 | C | t͡s | ᠼ |
1834 | J | d͡z | ᠽ |
1859 | x | x | ᡙ |
185A | `` | ᡚ | |
185B | `` | ᡛ | |
185C | `` | ᡜ |
Punctuations and symbols
Numbers
U+ | Keymap | Mongolian |
---|---|---|
1810 | 0 | ᠐ |
1811 | 1 | ᠑ |
1812 | 2 | ᠒ |
1813 | 3 | ᠓ |
1814 | 4 | ᠔ |
1815 | 5 | ᠕ |
1816 | 6 | ᠖ |
1817 | 7 | ᠗ |
1818 | 8 | ᠘ |
1819 | 9 | ᠙ |
Punctuations
U+ | Keymap | Mongolian | Manchu | Description |
---|---|---|---|---|
1801 | \ | ᠁ | N/A | Ellipsis for Mongolian. |
1802 | , | ᠂ | N/A | Comma for Mongolian. |
1803 | . | ᠃ | N/A | Full stop for Mongolian. |
1804 | : | ᠄ | N/A | Colon for Mongolian. |
1807 | ' | N/A | ᠇ | A bare tooth. "Glottal stop" letter; "Sibe syllable boundary marker" (SSBM). |
1808 | `` | N/A | ᠈ | Comma for Manchu. |
1809 | `` | N/A | ᠉ | Full stop for Manchu. |
180A | & | ᠊ | ᠊ | Letter stem (Nirugu). |
180B | ' | ᠋ | ᠋ | Free variation selector 1. |
180C | " | ᠌ | ᠌ | Free variation selector 2. |
180D | `` | ᠍ | ᠍ | Free variation selector 3. |
180E | _ | | N/A | Disjoint tail in Mongolian. "Mongolian vowel separator" (MVS). |
180F | `` | ᠏ | ᠏ | Free variation selector 4. |
200C | ^ | | | Zero-width non-joiner (ZWNJ). |
200D | * | | | Zero-width joiner (ZWJ). |
202F | - | Narrow non-breaking space (NNBSP). |
Additional notes on typing traditional Mongolian script using Raven
- Certain grammatical suffixes are preceded by a narrow non-breaking space (NNBSP), NOT a normal space, these suffixes are always written without any space in Cyrillic Mongolian.
- The disjoint tail (which is quite common), namely ᠠ, should always be preceded by an MVS (U+180E), NOT an NNBSP or a normal space.
- When typing the vowel ü/ү
ᠦ
(U+1826) in foreign words (usually get a в in Cyrillic), add an extra FVS1 (U+180B) after the letter. - When typing the consonant t/т
ᠲ
(U+1832) in foreign words, add an extra FVS1 after the letter, unless it sits at the beginning of the word. - When typing the consonant d/д
ᠳ
(U+1833) in foreign words, add an extra FVS1 after the letter, unless it sits in the middle of the word, and also before a vowel. - When typing a single long tooth in a falling diphthong, use a single
y
, noti
. E.g.: ᠨᠠᠶᠮᠠnayma
.
Additional notes on typing Manchu using Raven
Additional notes on typing Sibe using Raven
Seven letters in Sibe are different from Manchu, namely i, ŋ, k, f, j, zh and r. Be careful of the codepoints used in Sibe texts.
Tibetan
Rochelle
🔪 Stream chunk splitting.
Licensed under GNU LGPL 3.0. Named after Roach (Rochelle) in Cooking Roach and A Meal Fit for a King by Bucking Nonsense.
Modules
Text emitter
API
Static properties
SPLIT_UTF_8
: Split by UTF-8. Also used by encodings like Shift JIS.SPLIT_UTF_16LE
: Split by UTF-16LE.SPLIT_UTF_16BE
: Split by UTF-16BE.
Constructor
new TextEmitter(stream: ReadableStream, splitMode: Number, label: String);
stream
: The source stream of strings to read from.splitMode
: How to determine valid line feed (0x0a
) and carriage return (0x0d
) characters. Valid values are listed asSPLIT_*
static properties.label
: One of the valid labels. Not implemented.
Events
chunk
MessageEvent<Uint8Array>
When a raw chunk is received from the stream.
close
Event
When the stream or the emitter closes.
error
ErrorEvent
When the emitter encounters a critical error.
fail
MessageEvent<Uint8Array>
When a line of text becomes available, but decoding failed. Returns the raw bytes.
raw
MessageEvent<Uint8Array>
When a line of text becomes available before decoding begins. Returns the raw bytes.
Raw line data will be flushed from buffer when the stream closes unexpectedly.
text
MessageEvent<String>
When a line of text becomes available. Returns the decoded line of text.
Properties
closed
Not implemented.
Boolean: TextEmitter.closed
If the text emitter is closed.
Methods
close()
Not implemented.
undefined: TextEmitter.close()
Close the current stream.
shx
📜 Bash/PDKSH shell action executor. A replacement for npx
, deno task
and etc.
All actions for shx
should be written for Bash.
Supported shells
- AT&T
ksh93
- Directory traversal does not work on ksh93 due to incorrect
IFS
behaviour. - Cannot be used as a runner.
- Directory traversal does not work on ksh93 due to incorrect
- Bash
- Zsh
Usage
shx [<action> [<arguments>]]
Scripts will be run with Bash when present. If not, they'll be run with any supported shell.
Standard utilities
shx
comes with a collection of QoL standard utilities.
amend
: Update and amend the current commit, then push to remote.build
: A placeholder action for projects usingshx
to build themselves.commit
: Create a new commit, then push to remote.echob
: Printing bold text in the terminal.push
: A combination ofshx build
andshx commit
.release
: Bundle build results into an archive. Configurable (upcoming).sh
: Spawn a Nix-powered shell with all development dependencies met.tag
: Tag the current commit, then push the tag to remote.which
: Fallback for environments not offering awhich
command.
Silk
Silk is an attempt to unify timelines of the MLP fandom on the Fediverse. It is achieved by merging all public timelines of instances with Mastodon-compatible APIs, and accounts that followed this account if on other instances. To avoid stressing tracked servers and accounts, WebSocket and SSE connections are utilized whenever possible, with caches enforced.
By bringing the MLP fandom on the Fediverse together, we attempt to make the Fediverse an appealing place for bronies and pegasisters alike, without any grip from a commercial entity. Find interesting people, discover content creators, anything is possible.
Don't know what Fediverse is? In laymen's terms, it's a cluster of inter-connected servers supporting a semi-decentralized social network. It has no single controlling entity, rendering takeover attempts happened to the blue bird impossible. But those are just words, why not join the Fediverse to experience it first-hoof?
Don't know which server to join? A list of servers is available here!
- Inclusion: What's included in the timeline, and which server to join.
- Moderation: How we moderate the merged timeline.
- Usage: How to use Silk Web.
- API: How to use Silk API.
Technical implementation
The list of servers to merge timelines can be customized, while moderation on specific users are implemented with existing Mastodon features. Accounts muted by the hook account are excluded from any self-service exemptions, while ones blocked by the hook account are excluded from the timeline altogether.
Hook accounts
The primary hook account is used for storing moderation information. Other instances usually do not need a hook account to be set up to read the local timeline.
Not every instance has its public timeline open to everyone though. As such, additional hook accounts are required on these instances.
Below is the list of hook accounts.
- @[email protected] (primary)
- @[email protected]
Open Source
Silk is a piece of open source software, licensed under GNU AGPL 3.0 or later.
If ready for public use, source code would be available on GitHub.
Content Inclusion
Instances
Silk will attempt to merge public timelines on all servers listed below.
Non-CW
The following instances have posts' content warning set as-is.
- Equestria Social
- is-a.horse
- Our Town
- Mastopon
- Ponies on Mastodon
social.inex.rocks(closed due to Russian censorship)
CW by default
Due to differences of the server rules, all of the following instances have posts' content warning enabled by default to comply the moderation rules.
Excluded instances
Pone.Social (https://pone.social)(removed due to incorrect configuration on the instance)
Requesting instance inclusion
We're open to include more instances to the list. If you host an instance which satisfies the following criteria, please contact us to have your instance included. We will assess before the final inclusion.
- MLP-themed
- Not a roleplay instance
- Not supported by advertisement
Manual account inclusion
If your account isn't on any of the instances listed above, and said instance isn't mainly for the MLP community, you can follow the hook account to get yourself included manually. The hook account may also follow some accounts to have the same effect, mainly when said accounts do not have the ability to follow anyone (e.g. Equestria Daily).
Timeline Moderation
To grant as many members in the MLP community a pleasant experience as possible, we are enforcing a series of moderation rules on the merged timeline.
The rules are set on the basis of least intervention. They may change without prior notice, but we try our best to keep everyone notified.
Account exclusion
Accounts matching any criteria below will be excluded from the merged timeline altogether.
- Nearly always advertise presence on other platforms without mingling on the Fediverse
- Vent account
- Promotion of self-harm
- Promotion of hate speech, incl. racism, xenophobia, etc
- Owner involved in harming of other individuals
- Regularly not putting materials unsuitable for minors behind content warnings
- Having no connection to the MLP fandom whatsoever
Instance auto-CW
Instances that permit accounts with the aforementioned criteria will get put behind content warnings by default.
Instance auto-CW exemption per-account
If you are on a server with content warning automatically enabled in the timeline, you can exempt yourself from the auto-CW status by following the hook account, as long as you follow the following rules. However, matching any criteria listed before will get your auto-CW exemption status revoked, or even entirely excluded.
Silk API
All APIs are assumed to be hosted at api.ltgc.cc if without further clarification.
Endpoints
GET /nr/silk/servers
Grab a list of included servers, along with their auto-CW status.
Returns an array of Server
objects.
GET /nr/silk/timeline
Fetches a list of posts already stored on the server.
Returns an array of Post
objects.
WS/SSE /rt/silk/timeline
If there are changes made to the timeline, this endpoint will push such changes to the clients.
Sents EventWrapper
objects regardless of connection type.
Data structure
EventWrapper
{
"event": <String>, // "set", "delete", "ack"
"data": <Post|String|null>
}
Server
{
"domain": "example.com",
"cw": false,
"active": true
}
Post
Except for Post.card
and properties shown as null
here, the data structure of Post
objects have been pinned down.
Data of an example post is shown below.
{
"id": "110464545243574580",
"uri": "https://equestria.social/users/thatonegib/statuses/110464545243574580",
"url": "https://equestria.social/@thatonegib/110464545243574580",
"tags": [{
"name": "mlp",
"url": "https://equestria.social/tags/mlp"
}],
"emojis": [{
"code": "flutteryay",
"url": "https://equestria.social/system/custom_emojis/images/000/000/145/original/1295608.png",
"static": "https://equestria.social/system/custom_emojis/images/000/000/145/static/1295608.png",
"inPicker": true
}, {
"code": "ajsmug",
"url": "https://equestria.social/system/custom_emojis/images/000/000/088/original/1292830.png",
"static": "https://equestria.social/system/custom_emojis/images/000/000/088/static/1292830.png",
"inPicker": true
}],
"card": null,
"poll": {
"id": "49940",
"atExpire": 1685560245796,
"expired": false,
"multiple": false,
"sumVote": 0,
"sumVoter": 0,
"options": [{
"title": "Don't choose",
"sumVote": 0
},{
"title": "Don't choose either",
"sumVote": 0
}],
"emojis": []
},
"atNew": 1685555194757,
"replyPost": "110464545243574580",
"replyUser": "109524364471531266",
"cwReal": false,
"cwText": "",
"access": "public",
"lang": "en",
"sumReply": 1,
"sumBoost": 3,
"sumFav": 3,
"atEdit": 1685555194758,
"text": "<p>Day 7: The Church. (final)</p>",
"boost": null,
"app": {
"name": "Web",
"site": "https://joinmastodon.org/"
},
"user": {
"id": "109524364471531266",
"username": "thatonegib",
"acct": "thatonegib",
"dispName": "Gib Riel-Delano",
"locked": false,
"bot": false,
"discoverable": true,
"group": false,
"note": "<p>He/Him.<br />"Road to hell is paved with good intentions"<br />♥️ <br /><span class=\"h-card\"><a href=\"https://equestria.social/@AlzMarioWolfe\" class=\"u-url mention\">@<span>AlzMarioWolfe</span></a></span><br /> 💜 <br />@DamienInTheDark<br /> 04 Oct 2019<br />Comms CLOSED</p>",
"url": "https://equestria.social/@thatonegib",
"avatar": "https://equestria.social/system/accounts/avatars/109/524/364/471/531/266/original/8123b1c31f504128.jpg",
"avatarStatic": "https://equestria.social/system/accounts/avatars/109/524/364/471/531/266/original/8123b1c31f504128.jpg",
"header": "https://equestria.social/system/accounts/headers/109/524/364/471/531/266/original/e5cd38c16822e681.jpg",
"headerStatic": "https://equestria.social/system/accounts/headers/109/524/364/471/531/266/original/e5cd38c16822e681.jpg",
"sumPost": 58,
"atLastPost": "2023-05-31",
"noIndex": false,
"emojis": [],
"roles": [],
"fields": [{
"name": "Look through my Gallery!",
"value": "<a href=\"https://www.deviantart.com/thatonegib/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"\">deviantart.com/thatonegib/</span><span class=\"invisible\"></span></a>",
"atVerify": null
}, {
"name": "Help me make a living!",
"value": "<a href=\"https://www.patreon.com/ThatOneGib\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"\">patreon.com/ThatOneGib</span><span class=\"invisible\"></span></a>",
"atVerify": null
}, {
"name": "Watch the sauce get made!",
"value": "<a href=\"https://www.youtube.com/channel/UC2V6hQau5NkH4abuBFoFhyg\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"ellipsis\">youtube.com/channel/UC2V6hQau5</span><span class=\"invisible\">NkH4abuBFoFhyg</span></a>",
"atVerify": null
}, {
"name": "Obligatory Twatter link",
"value": "<a href=\"https://twitter.com/ThatOneGib\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://</span><span class=\"\">twitter.com/ThatOneGib</span><span class=\"invisible\"></span></a>",
"atVerify": null
}],
"atNew": 1671148800000,
"sumFan": 25,
"sumSub": 5
},
"media": [{
"id": "110464545127306536",
"type": "image",
"url": "https://equestria.social/system/media_attachments/files/110/464/545/127/306/536/original/4f8c3b035aede9ea.jpeg",
"preview": "https://equestria.social/system/media_attachments/files/110/464/545/127/306/536/small/4f8c3b035aede9ea.jpeg",
"remote": null,
"previewRemote": null,
"text": null,
"meta": {
"original": {
"width": 1015,
"height": 2042,
"size": "1015x2042",
"aspect": 0.4970617042115573
},
"small":{
"width": 338,
"height": 680,
"size": "338x680",
"aspect": 0.4970588235294118
}
},
"alt": "Alt text example",
"blurhash": "USAAX:WFMtogouocMyWBjXa$f,jZIUWBxukC"
}],
"ats": [{
"id": "110377043343501824",
"username": "silk",
"url": "https://equestria.social/@silk",
"acct": "silk"
}],
"handle": "@[email protected]",
"rid": "[email protected]"
}
Service Usage
For ease of use, Silk provides an API and a web frontend.
API
Please refer to API.
Web frontend
The web frontend is expected to become publicly available at mlp.ltgc.cc.
If you have internal access, you might also be able to try it out at staging.ltgc.cc (NXDOMAIN
expected).
Snowy
A BroadcastChannel
polyfill for Firefox 29+ and Chromium 5+, implemented with SharedWorker
.
Snowy will not be active if BroadcastChannel
already exists.
Usage
- Place
snowy.js
under the root directory of your website.- If
snowy.js
needs to be placed somewhere else, setself.SNOWY_PATH
to wheresnowy.js
resides.
- If
- Run
bc.js
in your page to start the polyfill.
SynPix
👾 The open pixel font for embedded LCDs.
SynPix is a union effort of GFHK-SDGM, PoneyClairDeLune and JayB.
Support
Unicode Blocks
- ASCII
- Latin-9
- Some additional Latin alphabets, see below for details
- IPA (U+0250 - U+029F)
- U+02C6 - U+02CF
- Monotonic Greek (lacking some bare diacritics)
- Cyrillic (only Russian, Ukrainian and pre-1918 Russian currently, see below for upcoming updates)
- Armenian
- Hebrew (basic letters only, no full Yiddish support yet)
- Georgian (upcoming in version 0.4)
- Cherokee (upcoming in version 0.4)
- Runes
- Tai Le
- New Tai Lüe (upcoming)
- Roman numerals (U+2160 - U+2165)
- Bagua symbols
- Astronomical symbols
- Zodiac symbols
- Coptic
- CJK radicals supplement (partial complete)
- Kangxi radicals (except 9 characters “⼢⼮⿋⿎⿏⿐⿒⿔⿕”)
- CJK symbols and punctuation (、。々〇「」)
- “Hangzhou” numerals
- Hiragana (missing 2 characters “ぱぽ”)
- Katakana (missing 1 character “パ”)
- Bopomofo
- Hangul compatibility jamo (done for modern jamos)
- CJKV Ideographs (see below for details)
- Lisu (Fraser alphabet)
- Phags-pa (upcoming in version 0.4)
- Full-width ASCII
- Half-width katakana
- Half-width Hangul
-
Various currency symbols (partial complete,
¢£¥€¢£¥
) - Gothic (upcoming?)
EU Official Languages
- Bulgarian (done in basic Cyrillics)
- Croatian (no tone marks yet)
- Czech
- Danish (done in Latin-9, except Ǿǿ, which is done in 0.3)
- Dutch (done in Latin-9, except digraph IJij, which is done in 0.3)
- English (done in ASCII)
- Estonian (done in Latin-9)
- Finnish (done in Latin-9)
- French (done in Latin-9)
- German (done in Latin-9, except uppercase ẞ, which is done in 0.3)
- Greek (currently monotonic only)
- Hungarian (upcoming in version 0.4)
- Irish (done in Latin-9 for modern orthography, old orthography upcoming in version 0.4)
- Italian (done in Latin-9)
- Latvian
- Lithuanian
- Maltese (upcoming in version 0.4)
- Polish
- Portuguese (done in Latin-9)
- Romanian (upcoming in version 0.4)
- Slovak
- Slovene (no tone marks yet)
- Spanish (done in Latin-9)
- Swedish (done in Latin-9)
Latin Alphabets
For the official languages of the European Union, refer to the list above.
- Serbo – Croatian (Latin) (no tone marks yet)
- Esperanto
Romanization Systems
- Hànyǔ Pīnyīn
Cyrillic Alphabets
- Russian
- Ukrainian (Ґґ Єє Іі Її)
- Pre-1918 Russian (four extra letters: Іі Ѣѣ Ѳѳ Ѵѵ)
- Belarusian (Іі, Ўў)
- Bulgarian
- Dungan (Cyrillic) (Җҗ Ңң Әә Ўў Үү, upcoming in version 0.4)
- Macedonian (Ѓѓ Ѐѐ Ѕѕ Ѝѝ Јј Љљ Њњ Ќќ Џџ)
- Mongolian (Cyrillic) (Өө Үү)
- Kazakh (Cyrillic) (Әә Ғғ Ққ Ңң Өө Ұұ Үү Һһ Іі)
- Kyrgyz (Ңң Өө Үү)
- Serbo – Croatian (Cyrillic) (Ђђ Јј Љљ Њњ Ћћ Џџ, no tone marks yet)
- Tajik (Ғғ Ӣӣ Ққ Ӯӯ Ҳҳ Ҷҷ)
- Tatar (Cyrillic) (Әә Җҗ Ңң Өө Үү Һһ, upcoming in version 0.4)
- Tuvan (Ңң Өө Үү)
- Uzbek (Cyrillic) (Ўў Ққ Ғғ Ҳҳ)
CJKV Ideographs
As of version 2023m27a, we currently have about 516 (?) unrepeated glyphs, 606 if counted the repeated ones.
㘯一丁七万丈三上下不丐丑丙丨个丫
中丰丶丸丹主丽丿乃久么义之乙九乞
也习乡书亅了予二于亏云互五井亜亞
亠亡亢亥京人亿什仁仃今介仑仓代令
以任会伝伟何你來侖修倉個偉傳億儿
兀兄兆光克党入八六兰共关其典冂円
冖冫冬几凡凵出刀刁刃力加劳労勇勝
勞勹勺匕北匚匸区區十千午华南卜卝
卤卩卯厂原厡厶去县又叉友发口可台
史司合向吕君吾呂告命和問善営囗囚
四回圆圓土在地场坂基堀場塲士壬声
夂处复夏夕多夜大天女威子孑孓存学
學宀它安宏官宝实実宠室宫宮家寅實
寵寶寸小少尔尢尸尹尼尽尾屮山川工
己已巳巴巷巾布帜幟干平年幸幺广広
庆库庚庫廠廣廴廾廿弋弓弥彌彐彡彥
彦彳復心志忘思恩恭恵悅惠慶戈戊戌
成我戶户戸所手才支攴攵政文斉斗斤
方施无日早时春昭昼時晝智暢曜曰書
會月木未本朱村来松某栄梁梅森榮欠
止正歹殳毅毋母比毛氏民气氣水汉污
河治沼沿法洽流浩海淸清港漢火点無
營爪父爻爾爿片牙牛犬玄玉王瓜瓦甘
生用田由甲申画畅畫疋疒癶癸發白百
皇皮皿盡目直県眞真矛矢知石示祭禸
禾私秋穴空立童竹範籐米糸紀細維網
縣纪细维缶网羊美羔義羽習翠老而耒
耳聲聿肉胜臣自至臺臼舌舛舟艮色艸
艹花草荣菊華营萬藤蘭虍處虧虫蟲血
行衣複襾西覆見见角言詩語論謠謡識
论识语谷豆豊豐豕豸貝贝赤走越足身
車転轉车转辛辰辱辵达过近送透造過
道達邑邓郷鄉鄕鄧酉酒釆里重金長长
門関闗關门问阜阳阴降陰陽隆隶隹雄
難雨雪靑青非面革韋韦韭音頁須页须
風风飛飞食首香馬馱駄马驮骨高髟鬥
鬯鬲鬼魔魚鯉鱼鲤鳥鸟鹵鹿麗麥麦麻
黃黄黍黑黒點黨黽黾鼎齊齐龍龙
Track me, senpai!
Exploiting reverse psychology to convince people switch to privacy-friendly browsers. Uses a combination of server-side detection and cookie storage.
Usage
Just deploy the page and the appropriate detection method.
Server-side detection
Server-side detection should not breach any privacy law, as the visitor is already supplying every possible information to the server.
Caddy
header Accept-CH "sec-ch-ua-full-version,ua-full-version,sec-ch-ua-full-version-list"
@chromeVictims {
header "Sec-CH-UA-Full-Version-List" *Chrom*
not header "Cookie" *track-me-senpai*
not path /track-me/*
}
@otherVictims {
header "Sec-CH-UA" `*"Google Chrome"*`
header "Sec-CH-UA" `*"Microsoft Edge"*`
header "Sec-CH-UA" `*"Edge"*`
header "Sec-CH-UA" `*"Opera"*`
header "Sec-CH-UA" `*Arc*`
not header "Cookie" *track-me-senpai*
not path /track-me/*
}
redir @chromeVictims "/track-me/?src={uri}"
redir @otherVictims "/track-me/?src={uri}"
Client-side detection
Client-side detection may breach privacy laws. It will be developed if requested.
WingBlade
WingBlade is an abstraction layer targeting multiple JavaScript runtimes simultaneously. No TypeScript support is considered.
Projects utilizing WingBlade are expected to write web-oriented platform-agnostic code. For the most part, unless a better measure is found, WingBlade adheres to the Deno API scheme.
API
Open Source
Silk is a piece of open source software, licensed under GNU LGPL 3.0 or later.
Source code is available on the following code hosting services.
System
WingBlade.rt.cores
Use
Report the amount of CPU cores.
Syntax
Number: WingBlade.rt.cores
WingBlade.rt.exit
Use
Exit the current runtime with given status code. 0
by default.
Syntax
undefined: WingBlade.rt.exit(Number: code = 0);
WingBlade.rt.memory
Use
Report memory usage of the current runtime. All values are in bytes.
Syntax
MemoryUsage: WingBlade.rt.memory
{
external: Number, // Memory associated with JS objects outside of the JS isolate.
free: Number, // The size of available RAM.
heapTotal: Number, // The total size of the heap of the JS engine.
heapUsed: Number, // The size of the heap used by the JS engine.
rss: Number, // Resident Set Size, aka memory occupied in RAM.
total: Number // The total size of the RAM.
}
WingBlade.rt.networkDefer
Use
Indicate whether or not the current runtime is only allowed network access during triggering.
Useful for serverless functions.
Syntax
Boolean: WingBlade.rt.networkDefer
WingBlade.rt.os
Use
Report the current operating system. Examples include windows
, darwin
and linux
.
Syntax
String: WingBlade.rt.os
WingBlade.rt.persist
Use
Indicate whether or not the current runtime executes persistent sessions. If reports false
, the runtime will only be activated upon triggering, and will be destroyed when the triggered tasks finish.
Useful for serverless functions.
Syntax
Boolean: WingBlade.rt.persist
WingBlade.rt.variant
Use
Report the name of the current runtime WingBlade runs on. Examples include Node
, Deno
and Bun
.
Syntax
String: WingBlade.rt.variant
WingBlade.rt.version
Use
Report the version of the current runtime WingBlade runs on.
Syntax
String: WingBlade.rt.version
Environment variables
Note
WingBlade.env
can also be used as a normal JavaScriptObject
.
WingBlade.env.get
Use
Return an environment variable, and supply a fallback value if given.
Syntax
?String: WingBlade.env.get(String: key, ?String: fallbackValue);
WingBlade.env.set
Use
Set an environment variable with given value.
Syntax
undefined: WingBlade.env.set(String: key, String: value);
WingBlade.env.delete
Use
Remove an environment variable.
Syntax
undefined: WingBlade.env.delete(String: key);
WingBlade.env.has
Use
Indicate whether or not an environment variable exists.
Syntax
Boolean: WingBlade.env.has(String: key);
WingBlade.env.toObject
Use
Return a snapshot of all current environment variables as an Object
.
Syntax
Object: WingBlade.env.toObject();
Filesystem
WingBlade.file.read()
Use
Read the whole file as Uint8Array
.
Syntax
Promise<Uint8Array>: WingBlade.file.read(String: path, Object<ReadFileOptions>: opt);
Read Deno.ReadFileOptions
for the opt
params.
WingBlade.file.write()
Use
Write the whole Uint8Array
as a file.
Syntax
Promise<undefined>: WingBlade.file.write(String: path, Uint8Array: data, Object<WriteFileOptions>: opt);
Read Deno.WriteFileOptions
for the opt
params.
Utilities
WingBlade.util.randomInt
Use
Return a random integer between 0 (inclusive) and a value given (exclusive).
Syntax
Number: WingBlade.util.randomInt(Number: cap);
WingBlade.util.sleep
Use
Sleep for a given amount of time (in milliseconds).
Syntax
Promise<undefined>: WingBlade.util.sleep(Number: ms, ?Number: maxAdd = 0);
Networking
Web services
WingBlade.web.serve
Use
Start a web server with a handler function.
Syntax
WebServer: WingBlade.web.serve(AsyncFunction<Response>: handler, ?ServeInit: opt = {});
Read ServeInit@std/http/server
for more details.
handler
let handler = async function (Request: request, ConnInfo: connInfo) {
return new Response();
};
WingBlade.web.acceptWs
Use
Upgrade the incoming request to a WebSocket connection.
Syntax
UpgradedWebSocket: WingBlade.web.acceptWs(Request: req, UpgradeWebSocketOptions: opt);
UpgradedWebSocket
{
response: Response, // The upgrade response for the client
socket: WebSocketServer // Server-side WebSocket
}
UpgradeWebSocketOptions
{
protocol: String,
idleTimeout: Number
}
Read Deno.UpgradeWebSocketOptions for details.
WingBlade.web.acceptSSE
Use
Upgrade the incoming request to a Server-sent Event (EventSink
) connection.
Syntax
UpgradedSSE: WingBlade.web.acceptSSE(Request: req);
UpgradedSSE
{
response: Response, // The upgrade response to the client
socket: EventSink // Server-side EventSource
}
Web Stream
Quick ReadableStream
convertion
Warning
If the stream exploits the same
ArrayBuffer
to emit chunks, at least on Deno, all of the readings will error out.The Deno implementation may take twice as much RAM usage as on other runtimes.
ReadableStream.prototype.array()
ReadableStream.prototype.arrayBuffer()
ReadableStream.prototype.blob()
ReadableStream.prototype.json()
ReadableStream.prototype.text()
Stream behaviour modification
ChokerStream
Use
Apply chunk-size normalization to the attached stream.
The chunk first gets written to the normalized buffer, and if the buffer exceeds the target chunk size, a normalized chunk will get emitted. If the attached stream closes, all remaining data in the buffer will also be emitted.
Syntax
let object = new ChokerStream(Number: maxChunkSize = 1024, Boolean: alwaysCopy = false);
ChokerStream {
alwaysCopy: Boolean, // Read-only. Disables zero-copy when available if set to true.
chunk: Number, // A positive integer defining the normalized chunk size.
source: ReadableStream, // Get the choked readable stream.
sink: ReadableStream, // Read-only. The attached readable stream source.
attach: function () {} // Attach to a readable stream source.
}