ORGPILLED BABEY
This commit is contained in:
parent
3c88354f49
commit
10854fc28e
17
.eleventy.js
17
.eleventy.js
|
@ -1,17 +0,0 @@
|
|||
const { DateTime } = require("luxon");
|
||||
const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
|
||||
|
||||
module.exports = function(eleventyConfig) {
|
||||
eleventyConfig.addPlugin(pluginSyntaxHighlight);
|
||||
|
||||
eleventyConfig.addPassthroughCopy("stylesheets");
|
||||
|
||||
eleventyConfig.addFilter("readableDate", dateObj => {
|
||||
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat("dd LLL yyyy");
|
||||
});
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
||||
eleventyConfig.addFilter('htmlDateString', (dateObj) => {
|
||||
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
|
||||
});
|
||||
};
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
_site
|
||||
node_modules
|
||||
*.html
|
||||
*.xml
|
||||
stylesheets
|
||||
|
|
22
Dockerfile
22
Dockerfile
|
@ -1,12 +1,24 @@
|
|||
FROM node:lts-alpine as builder
|
||||
FROM node:lts-alpine as css
|
||||
|
||||
WORKDIR /garbage
|
||||
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
RUN npm install -g sass
|
||||
COPY sass sass
|
||||
RUN mkdir stylesheets
|
||||
RUN sass sass:stylesheets
|
||||
|
||||
FROM alpine:3.15 as emacs
|
||||
WORKDIR /garbage
|
||||
|
||||
RUN apk --no-cache add \
|
||||
emacs
|
||||
|
||||
COPY . .
|
||||
RUN npx @11ty/eleventy
|
||||
|
||||
RUN emacs --batch --load setup.el
|
||||
RUN emacs --batch --load publish.el
|
||||
|
||||
FROM nginx:stable-alpine
|
||||
COPY --from=builder /garbage/_site/ /usr/share/nginx/html
|
||||
COPY --from=css /garbage/stylesheets /usr/share/nginx/html/stylesheets
|
||||
COPY --from=emacs /garbage/*.html /usr/share/nginx/html/
|
||||
COPY --from=emacs /garbage/*.xml /usr/share/nginx/html/
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="{{ renderData.description or description or metadata.description }}" />
|
||||
|
||||
<title>{{ renderData.title or title or metadata.title }}</title>
|
||||
|
||||
<link href="https://unpkg.com/prismjs@1.20.0/themes/prism-okaidia.css" type="text/css" rel="stylesheet" />
|
||||
<link href="/stylesheets/screen.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
<link href="/stylesheets/print.css" rel="stylesheet" type="text/css" media="print" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><a href="/" title="root">🖥😩</a></h1>
|
||||
<h2>stop touching the computer</h2>
|
||||
</header>
|
||||
<main>
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
<article>
|
||||
<h3><a href="{{ url }}" title="Permanent link">{{ title }}</a>
|
||||
<time datetime={{ date | htmlDateString }}>{{ date | readableDate }}</time></h3>
|
||||
{{ content | safe }}
|
||||
</article>
|
0
drafts/.keep
Normal file
0
drafts/.keep
Normal file
12
index.njk
12
index.njk
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
|
||||
{% for post in collections.post | reverse %}
|
||||
<ul>
|
||||
<li><a href="{{ post.url }}" title="Permanent link">{{ post.data.title }}</a> (<time datetime={{ post.date | htmlDateString }}>{{ post.date | readableDate }}</time>)
|
||||
<br />
|
||||
<span>{{ post.data.description }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
{% endfor %}
|
3106
package-lock.json
generated
3106
package-lock.json
generated
File diff suppressed because it is too large
Load diff
20
package.json
20
package.json
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "garbage",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^0.12.0",
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1",
|
||||
"luxon": "^2.0.0"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"esversion": 8
|
||||
}
|
||||
}
|
299
posts/email.md
299
posts/email.md
|
@ -1,299 +0,0 @@
|
|||
---
|
||||
title: How to Add Needless Complexity to Your Life
|
||||
date: 2014-10-30
|
||||
description: How to make email suck even more.
|
||||
layout: layouts/post.njk
|
||||
tags: post
|
||||
---
|
||||
|
||||
I used Apple Mail forever until recently, when my Exchange account starting
|
||||
causing it to blow itself up. Instead of installing Thunderbird and moving on
|
||||
with my life, I decided it was a good idea to start being a Serious Email User,
|
||||
and so I installed the Serious Email Client [mutt](http://www.mutt.org). But
|
||||
since this is a piece of Serious Software, there wasn't any easy-to-find, good
|
||||
documentation focused on actually *sending and receiving email* as opposed to
|
||||
Installing and Configuring mutt. (Even [the hard-to-find
|
||||
ones](http://curvedthoughts.com/blog/email-using-getmail-msmtp-mutt/ "Manage
|
||||
email using getmail, msmtp, and mutt") didn't go in-depth enough, and weren't
|
||||
written for OS X.) So this my attempt to get everything necessary---and nothing
|
||||
more---written down in one place.
|
||||
|
||||
#### mutt is just for reading email
|
||||
|
||||
The program mutt was not originally designed to do the actual sending and
|
||||
receiving of email. It can do that now, but it was built as a way to view local
|
||||
mail and to compose messages (except not really---you do the actual writing in
|
||||
your `$EDITOR`). Mail is fetched from a mail server using another program---I'll
|
||||
be using [getmail](http://pyropus.ca/software/getmail/). Mail is sent using yet
|
||||
another program---[msmtp](http://msmtp.sourceforge.net).
|
||||
|
||||
And there's no point in having mutt if you've got nothing to read, so before we
|
||||
even bother installing mutt we're going to set up getmail.
|
||||
|
||||
#### you get mail with getmail
|
||||
|
||||
The easiest way to install getmail is with
|
||||
[Homebrew](http://brew.sh "The missing package manager for OS X"):
|
||||
|
||||
```text
|
||||
brew install getmail
|
||||
```
|
||||
|
||||
The official [configuration
|
||||
documentation](http://pyropus.ca/software/getmail/configuration.html) is not
|
||||
always very clear, but it is comprehensive. So we'll try to simplify it here,
|
||||
with some help from [the
|
||||
blogosphere](http://curvedthoughts.com/blog/email-using-getmail-msmtp-mutt/
|
||||
"Manage email using getmail, msmtp, and mutt").
|
||||
|
||||
First set up the config directory, with restricted permissions for Serious
|
||||
Security:
|
||||
|
||||
```text
|
||||
mkdir -m 700 ~/.getmail
|
||||
```
|
||||
|
||||
In that folder you'll need to set up a config file for each email account you
|
||||
want to retrieve messages from. If you just have one, name the file `getmailrc`,
|
||||
which is what getmail looks for by default. The examples below are for setting
|
||||
up a Gmail account, so I named the below config file `gmailrc`:
|
||||
|
||||
```text
|
||||
[retriever]
|
||||
type = SimpleIMAPSSLRetriever
|
||||
server = imap.gmail.com
|
||||
port = 993
|
||||
mailboxes = ALL
|
||||
username = gmail-address
|
||||
ssl_version = tlsv1_2
|
||||
|
||||
[destination]
|
||||
type = Maildir
|
||||
path = ~/Mail/gmail/
|
||||
|
||||
[options]
|
||||
message_log = ~/.getmail/gmail.log
|
||||
read_all = false
|
||||
|
||||
```
|
||||
|
||||
The most common alternative to `SimpleIMAPSSLRetriever` is probably
|
||||
`SimplePOP3SSLRetriever`, but there are [lots of types supported by
|
||||
getmail](http://pyropus.ca/software/getmail/configuration.html#conf-retriever).
|
||||
|
||||
If you only want to download your inbox, don't specify `mailboxes`. If
|
||||
you want to download a subset of your mailboxes, replace
|
||||
`mailboxes = ALL` with a list of desired mailboxes in the following
|
||||
format:
|
||||
|
||||
```text
|
||||
mailboxes = ("INBOX", "INBOX.spam")
|
||||
```
|
||||
|
||||
getmail's `ssl_version` [defaults to
|
||||
SSLv23](http://pyropus.ca/software/getmail/configuration.html#retriever-ssl-extra),
|
||||
which needs to be overridden since it allows SSLv3, which is now [known
|
||||
to be vulnerable](http://poodlebleed.com).
|
||||
|
||||
Replace `gmail-address` with your full Gmail email address, then create
|
||||
a Maildir directory structure in `~/Mail/gmail`:
|
||||
|
||||
```text
|
||||
mkdir -m 700 -p ~/Mail/gmail/{cur,new,tmp}
|
||||
```
|
||||
|
||||
(getmail supports
|
||||
[mbox](http://qmail.org/qmail-manual-html/man5/mbox.html) in addition to
|
||||
Maildir; I don't really know the relative strengths and weaknesses but I
|
||||
went with Maildir ¯\\\_(ツ)\_/¯.)
|
||||
|
||||
The `[options]` are not required, but `read_all = false` is a very good
|
||||
idea (especially with `mailboxes = ALL`) because otherwise getmail will
|
||||
download all your mail every time you run it.
|
||||
|
||||
You can specify `password` in your config file, but then it's sitting
|
||||
there in plain text and that's Bad. So instead, add the password to
|
||||
Keychain Access:
|
||||
|
||||
```text
|
||||
security add-internet-password -a 'gmail-address' -s 'imap.gmail.com' -r imap -P 993 -w app-specific-password
|
||||
```
|
||||
|
||||
Replace `gmail-address` again with your full Gmail email address, and
|
||||
`app-specific-password` with a [Google App
|
||||
Password](https://support.google.com/accounts/answer/185833 "Google Support").
|
||||
|
||||
**Important:** if your password has characters like `$` that shells
|
||||
treat specially, make sure to put single quotes around the whole
|
||||
password.
|
||||
|
||||
Then run getmail, with the `--rcfile` flag if you have config files that
|
||||
aren't named `getmailrc` (you can use the flag multiple times):
|
||||
|
||||
```text
|
||||
getmail --rcfile=gmailrc --rcfile=otheraccount
|
||||
```
|
||||
|
||||
Add that command to your [cron
|
||||
jobs](https://help.ubuntu.com/community/CronHowto) or use [Apple's
|
||||
`launchd`](http://nathangrigg.net/2012/07/schedule-jobs-using-launchd/)
|
||||
to run it regularly.
|
||||
|
||||
#### *then* you install mutt
|
||||
|
||||
```text
|
||||
brew install mutt --with-gpgme --with-confirm-attachment-patch
|
||||
```
|
||||
|
||||
The `--with-gpgme` flag enables [GPGME (GnuPG Made
|
||||
Easy)](https://www.gnupg.org/related_software/gpgme/), which is
|
||||
apparently [the right way to do encryption with
|
||||
mutt](http://henrytodd.org/notes/2014/simpler-gnupg-mutt-config-with-gpgme/).
|
||||
The `--with-confirm-attachment-patch` flag causes mutt to warn you
|
||||
before sending a message with "attach" in the body but no attachment.
|
||||
Both of these flags are optional, and there are other flags you might
|
||||
want to add; see `brew info mutt`.
|
||||
|
||||
The only setting you *have* to add to your mutt configuration file (by
|
||||
default, `~/.muttrc`) is `set mbox_type=Maildir` (or
|
||||
`set mbox_type=mbox` as the case may be). You'll probably want to
|
||||
specify the location of your Gmail folder, though:
|
||||
|
||||
```text
|
||||
set mbox_type=Maildir
|
||||
set folder = "~/Mail/gmail/"
|
||||
set spoolfile = "~/Mail/gmail/"
|
||||
set record = "~/Mail/gmail/sent/"
|
||||
```
|
||||
|
||||
The `sent` folder is technically another Maildir box, so you'll need to
|
||||
populate it with the same three folders:
|
||||
|
||||
```text
|
||||
mkdir -m 700 -p ~/Mail/gmail/sent/{cur,new,tmp}
|
||||
```
|
||||
|
||||
Fine-tuning your configuration and getting comfortable with the program
|
||||
isn't what this post is about; take a look at [sample `.muttrc`
|
||||
files](http://curvedthoughts.com/blog/email-using-getmail-msmtp-mutt/ "Manage email using getmail, msmtp, and mutt"),
|
||||
Steve Losh's [excellent
|
||||
guide](http://stevelosh.com/blog/2012/10/the-homely-mutt/ "The Homely Mutt")
|
||||
and the list of [mutt
|
||||
commands](http://www.mutt.org/doc/manual/manual-6.html#functions).
|
||||
|
||||
I will mention one customization that I had to come up with for reading
|
||||
HTML emails on OS X. It's easy enough to [pass HTML emails and HTML
|
||||
attachments to a text-based
|
||||
browser](http://www.debian-administration.org/article/75/Reading_HTML_email_with_Mutt "Debian Administration: Reading HTML email with Mutt")
|
||||
like lynx or w3m, but when I get [Today in
|
||||
Tabs](http://tinyletter.com/todayintabs) I want to be able to *open the
|
||||
tabs* in Safari or whatever real browser I usually use. You can [pass
|
||||
links from w3m to
|
||||
Firefox](http://superuser.com/questions/422692/open-current-page-in-w3m-in-firefox)
|
||||
if you're using Linux, but on OS X you'd have to be using w3m from
|
||||
within emacs to be able to do that. [Piping the HTML directly to
|
||||
Safari](http://hints.macworld.com/article.php?story=20051122200920326)
|
||||
doesn't work either, because the temporary file that mutt creates has
|
||||
the `.txt` extension, so Safari doesn't render the HTML. My solution is
|
||||
to add this to your `.muttrc`:
|
||||
|
||||
```text
|
||||
macro pager \cb <pipe-entry>'cat > /tmp/mutt_mail.html; open /tmp/mutt_mail.html'<enter> 'open email in default browser'
|
||||
```
|
||||
|
||||
When you hit `^b` (control-b) while viewing an HTML message or
|
||||
attachment, what that does is spit the HTML into a temporary file, then
|
||||
open it in your default browser.
|
||||
|
||||
(I wouldn't have figured this out if not for [Bruno Postle's page on
|
||||
following
|
||||
links](http://mutt.blackfish.org.uk/following-links/ "my first mutt").)
|
||||
|
||||
#### and send mail with msmtp
|
||||
|
||||
By now you know the drill:
|
||||
|
||||
```text
|
||||
brew install msmtp
|
||||
```
|
||||
|
||||
Then set up your [configuration
|
||||
file](http://msmtp.sourceforge.net/doc/msmtp.html#Configuration-files),
|
||||
with permissions set to `600`, at `~/.msmtprc`:
|
||||
|
||||
```text
|
||||
defaults
|
||||
tls on
|
||||
tls_starttls on
|
||||
tls_trust_file [see below]
|
||||
logfile ~/Mail/msmtp.log
|
||||
|
||||
account gmail-address
|
||||
host smtp.gmail.com
|
||||
port 587
|
||||
protocol smtp
|
||||
auth on
|
||||
from gmail-address
|
||||
user gmail-address
|
||||
```
|
||||
|
||||
OS X doesn't have the `/etc/ssl/certs/ca-certificates.crt` file that
|
||||
some Linux systems do. All our certificates are in the Keychain Access
|
||||
application; so we need to export them:
|
||||
|
||||
1. Open Keychain Access
|
||||
(`open -a /Applications/Utilities/Keychain\ Access.app/`).
|
||||
|
||||
2. From the "Keychains" column, select "System Roots."
|
||||
|
||||
3. Select All, then go to File → Export Items... (`⇧⌘E`).
|
||||
|
||||
4. Save the `.pem` file wherever, then set `tls_trust_file` to the path
|
||||
to it (for example, `~/Mail/certs/Certificates.pem`).
|
||||
|
||||
Then return to your `.muttrc` and add:
|
||||
`set sendmail = "/usr/local/bin/msmtp"`
|
||||
|
||||
Add another Keychain entry:
|
||||
|
||||
```text
|
||||
security add-internet-password -a 'gmail-address' -s 'smtp.gmail.com' -r smtp -P 587 -w app-specific-password
|
||||
```
|
||||
|
||||
Again, replace `gmail-address` with your full Gmail email address, and
|
||||
`app-specific-password` with a [Google App
|
||||
Password](https://support.google.com/accounts/answer/185833 "Google Support").
|
||||
|
||||
#### yay
|
||||
|
||||
At this point you should be able to send and receive email using mutt!
|
||||
Wooooww. Now you can dick around with further niceties:
|
||||
|
||||
- Encrypt your emails. If you already have GPG installed, [following
|
||||
these
|
||||
instructions](http://henrytodd.org/notes/2014/simpler-gnupg-mutt-config-with-gpgme/)
|
||||
will probably work. Otherwise `brew install gnupg gpg-agent` and
|
||||
[get them set up](https://wiki.archlinux.org/index.php/Gnupg).
|
||||
|
||||
(If you start mutt and get the error message *"Using GPGME backend,
|
||||
although no gpg-agent is running,"* gpg-agent may be [running in a
|
||||
different shell
|
||||
session](http://lists.gnupg.org/pipermail/gnupg-users/2007-May/031024.html)---this
|
||||
might occur if you're using a terminal multiplexer like screen or
|
||||
tmux, or if you're using the
|
||||
[GPGTools](https://gpgtools.org)-supplied gpg-agent.)
|
||||
|
||||
- `brew install lbdb` and create `~/.lbdbrc` with the following lines
|
||||
to link Contacts.app to mutt:
|
||||
|
||||
METHODS="m_muttalias m_osx_addressbook"
|
||||
MUTT_DIRECTORY="$HOME/.mutt"
|
||||
MUTTALIAS_FILES=".muttrc .mail_aliases muttrc aliases"
|
||||
|
||||
Then add `set query_command="/usr/local/bin/lbdbq '%s'"` to your
|
||||
`.muttrc`, and use `^t` (control-t) to auto-complete addresses.
|
||||
(This is adapted from [bluehz's
|
||||
instructions](http://hints.macworld.com/article.php?story=20041024163030501).)
|
||||
|
||||
- [Set up emacs as your message
|
||||
editor](http://www.emacswiki.org/emacs/MuttInEmacs)
|
287
posts/libgen.md
287
posts/libgen.md
|
@ -1,287 +0,0 @@
|
|||
---
|
||||
title: The Library Genesis API
|
||||
date: 2014-10-01
|
||||
description: An English-language guide to using the LibGen API.
|
||||
layout: layouts/post.njk
|
||||
tags: post
|
||||
---
|
||||
|
||||
[Library Genesis](http://libgen.io/) has an API, but the only documentation is
|
||||
[a forum thread in Russian](http://genofond.org/viewtopic.php?p=39355 "The
|
||||
Library Genesis Miner's Hut"). So this is an English-language guide to using
|
||||
the LibGen API.
|
||||
|
||||
(I don't know Russian, and had to read the original thread using [Google
|
||||
Translate](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fgenofond.org%2Fviewtopic.php%3Fp%3D39355),
|
||||
so corrections and additions are very welcome!)
|
||||
|
||||
#### First, some bad news
|
||||
|
||||
*This is not a search API.*
|
||||
|
||||
The API was apparently written to help LibGen maintainers keep their
|
||||
local mirrors up-to-date, which would explain why the API does not
|
||||
support the most common use that Library Genesis is put to by the rest
|
||||
of us: searching for texts. You can't (as far as I can tell) submit a
|
||||
string and get a list of results based on that string.
|
||||
|
||||
There are two *documented* ways to use the API to query the LibGen
|
||||
database: by text ID, or by date.
|
||||
|
||||
#### Querying by ID
|
||||
|
||||
Here's how to retrieve information about the texts with the coveted IDs
|
||||
of `1` and `2`:
|
||||
|
||||
```text
|
||||
curl 'http://libgen.io/json.php?ids=1,2&fields=Title,Author,MD5'
|
||||
```
|
||||
|
||||
(The API is available at `http://gen.lib.rus.ec/json.php` as well.)
|
||||
|
||||
The above `curl` request will return an array of JSON objects:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"title":"Handbook of Clinical Drug Data",
|
||||
"author":"Philip Anderson",
|
||||
"md5":"7B2A4D53FDE834E801C26A2BAB7E0240"
|
||||
},
|
||||
{
|
||||
"title":"Handbook of Herbs and Spices",
|
||||
"author":"K V Peter",
|
||||
"md5":"048EA0496DB0444F873139CD705A07AF"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
I used these three fields -- `title`, `author`, and `md5` -- because
|
||||
they're all you need in most situations. You can get the page URL by
|
||||
appending the MD5 to `http://libgen.io/book/index.php?md5=` or to one of
|
||||
the mirrors:
|
||||
|
||||
- `http://gen.lib.rus.ec/book/index.php?md5=`
|
||||
- `http://bookzz.org/md5/`
|
||||
- `http://bookfi.org/md5/`
|
||||
|
||||
You can create a download URL by appending the MD5 to
|
||||
`http://libgen.io/get.php?md5=`.
|
||||
|
||||
There are other mirrors whose URLs are based on the text's LibGen ID,
|
||||
rather than the MD5:
|
||||
|
||||
- `http://libgen.net/view.php?id=`
|
||||
- `http://www.libgen.net/view.php?id=`
|
||||
- `http://libgen.iofo/view.php?id=`
|
||||
- `http://lib.freescienceengineering.org/view.php?id=`
|
||||
|
||||
You can't get a direct download link for these; you have to go to the
|
||||
page for the text and download from there.
|
||||
|
||||
But `title`, `author`, and `md5` are far from the only available data
|
||||
fields; the full list is below. I haven't figured out what all the
|
||||
fields mean, and keep in mind that it's up to the person uploading a
|
||||
text to add this metadata, so not all texts are well-annotated.
|
||||
|
||||
- `id` -- the LibGen ID
|
||||
- `title` -- the title of the text
|
||||
- `volumeinfo` -- the volume number, if the text is part of a
|
||||
multi-volume series
|
||||
- `series` -- the series that the text is part of
|
||||
- `periodical`
|
||||
- `author` -- the author of the text
|
||||
- `year` -- the publication date of the text
|
||||
- `edition` -- the edition of the text
|
||||
- `publisher` -- the publisher of the text
|
||||
- `city` -- the location of the publisher
|
||||
- `pages` -- the number of pages in the text
|
||||
- `language` -- the language of the text
|
||||
- `topic` -- A number corresponding to the topic of the text; for
|
||||
example, `130` is "Mathematics/Logic"
|
||||
- `library`
|
||||
- `issue`
|
||||
- `identifier` -- the text's short and long [International Standard
|
||||
Book Numbers](https://www.isbn-international.org/content/what-isbn)
|
||||
(not necessarily in that order)
|
||||
- `issn` -- the text's [International Standard Serial
|
||||
Number](http://www.issn.org/understanding-the-issn/what-is-an-issn/)
|
||||
- `asin` -- the text's [Amazon Standard Identification
|
||||
Number](http://www.amazon.com/gp/seller/asin-upc-isbn-info.html)
|
||||
- `udc` -- the text's [Universal Decimal
|
||||
Classification](https://en.wikipedia.org/wiki/Universal_Decimal_Classification "Wikipedia entry")
|
||||
number
|
||||
- `lbc`
|
||||
- `ddc` -- the text's [Dewey Decimal
|
||||
Classification](https://en.wikipedia.org/wiki/Dewey_Decimal_Classification "Wikipedia entry")
|
||||
number
|
||||
- `lcc` -- the text's [Library of Congress
|
||||
Classification](https://en.wikipedia.org/wiki/Library_of_Congress_Classification "Wikipedia entry")
|
||||
number
|
||||
- `doi` -- the file's [Digital Object
|
||||
Identifier](https://en.wikipedia.org/wiki/Digital_object_identifier "Wikipedia entry")
|
||||
- `googlebookid` -- the text's [Google Books
|
||||
ID](https://developers.google.com/books/docs/v1/using#ids)
|
||||
- `openlibraryid` -- the text's [Open Library
|
||||
ID](https://openlibrary.org/dev/docs/api/books)
|
||||
- `commentary`
|
||||
- `dpi`
|
||||
- `color`
|
||||
- `cleaned`
|
||||
- `orientation`
|
||||
- `paginated` -- the text is paginated (`1`) or not (`0`)
|
||||
- `scanned` -- the text is scanned from a physical copy (`1`) or not
|
||||
(`0`)
|
||||
- `bookmarked` -- the text has bookmarks (`1`) or not (`0`)
|
||||
- `searchable` -- the text is searchable (`1`) or not (`0`)
|
||||
- `filesize` -- the size of the file in bytes
|
||||
- `extension` -- the extension of the file (`.pdf`, `.epub`, `.mobi`,
|
||||
etc.)
|
||||
- `md5` -- the [MD5](http://www.md5.net) hash of the file
|
||||
- `crc32` -- the file's
|
||||
[CRC32](http://www.riccibitti.com/crcguide.htm "A painless guide to CRC error detection algorithms")
|
||||
checksum
|
||||
- `edonkey` -- the file's [eDonkey
|
||||
hash](https://en.wikipedia.org/wiki/Ed2k_URI_scheme "Wikipedia entry")
|
||||
- `aich` -- the text's [eMule file
|
||||
hash](http://www.emule-project.net/home/perl/help.cgi?l=1&rm=show_topic&topic_id=589)
|
||||
- `sha1` -- the file's
|
||||
[SHA-1](https://en.wikipedia.org/wiki/SHA-1 "Wikipedia entry") hash
|
||||
- `tth` -- the file's [Tiger tree
|
||||
hash](https://en.wikipedia.org/wiki/Merkle_tree#Tiger_tree_hash "Wikipedia entry")
|
||||
- `generic`
|
||||
- `filename` -- the name of the file in the LibGen database, in the
|
||||
form `directory/md5`. The directory name is the text's LibGen ID
|
||||
rounded to the nearest thousand, and the MD5 hash is in lowercase.
|
||||
(The directory that each file is located in is [also included in the
|
||||
file
|
||||
name](https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/util.php#L6 "LibGen code on GitHub").)
|
||||
- `visible`
|
||||
- `locator` -- [As far as I can
|
||||
tell](https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/librarian/form.php#L187 "LibGen code on GitHub"),
|
||||
this is the file path of the original file on the machine of whoever
|
||||
uploaded it.
|
||||
- `local`
|
||||
- `timeadded` -- the date/time when the text was added to the database,
|
||||
formatted as `YYYY-MM-DD HH:MM:SS`
|
||||
- `timelastmodified` -- the date/time when the text's entry in the
|
||||
database was edited, formatted as `YYYY-MM-DD HH:MM:SS`
|
||||
- `coverurl` -- the path to the cover image for the text: the
|
||||
`filename` followed by a lowercase letter (there's [a
|
||||
function](https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/book/util.php#L30 "LibGen code on GitHub")
|
||||
to determine the letter for each cover, but I don't know enough PHP
|
||||
to understand it).
|
||||
|
||||
If you want to get all fields for a text, use `fields=*`.
|
||||
|
||||
#### Searching by date
|
||||
|
||||
Querying by ID is pretty useless except for internal tasks, so it's the
|
||||
ability to search by date that makes the API at all interesting. When
|
||||
searching by date, you don't send the `id` parameter to the API, but
|
||||
instead use some of the parameters below (along with any of the data
|
||||
fields from above):
|
||||
|
||||
- `mode` -- set to `last`, `modified`, or `newer`
|
||||
- `timefirst` -- a date formatted as `YYYY-MM-DD`
|
||||
- `timelast` -- a date formatted as `YYYY-MM-DD`
|
||||
- `timenewer` -- a time formatted as `YYYY-MM-DD%20HH:MM:SS`
|
||||
- `idnewer` -- a LibGen ID
|
||||
- `limit1` -- an integer
|
||||
- `limit2` -- an integer
|
||||
|
||||
Using these parameters allows you to do two things:
|
||||
|
||||
- ~~retrieve information about a random set of texts from within a
|
||||
specified date range,~~ (see below) or
|
||||
|
||||
- retrieve information about texts modified after a certain time.
|
||||
|
||||
#### The grab-bag method
|
||||
|
||||
~~The obvious use case for this method is to display a random text or
|
||||
set of texts (perhaps for a Twitter bot).~~ **I obviously didn't test
|
||||
the API enough,** because this method is *not* random. I'll look into it
|
||||
more when I have the time.
|
||||
|
||||
The following parameters and values are allowed here:
|
||||
|
||||
- `mode` -- either `last` or `modified`. If you use `last`, the API
|
||||
will match the dates you specify against text's `timeadded`; if you
|
||||
use `modified`, it will look at `timelastmodified`.
|
||||
|
||||
- `timefirst` -- the API will not return texts before this date
|
||||
(checked against either `timeadded` or `timelastmodified` depending
|
||||
on what the `mode` is set to). The first books have a `TimeAdded`
|
||||
value of `2009-07-20`, and setting `timefirst` to an earlier date
|
||||
will return an SQL error from the API.
|
||||
|
||||
- `timelast` (optional) -- the API will not return texts after this
|
||||
date.
|
||||
|
||||
- `limit1` and `limit2` (both optional) -- if both of these parameters
|
||||
are set, the number of results returned will be the value of
|
||||
`limit2`, and the set of results will be offset by the value of
|
||||
`limit1` (not very important here, where the results are random). If
|
||||
only `limit1` is set, its value is the number of results returned.
|
||||
|
||||
Here's an example. This query returns 10 ~~random~~ MD5 hashes for texts
|
||||
added between 1 May 2013 and 1 January 2014:
|
||||
|
||||
```text
|
||||
curl 'http://libgen.io/json.php?fields=MD5&limit1=10&mode=last&timefirst=2013-05-01&timelast=2014-01-01'
|
||||
```
|
||||
|
||||
#### The `newer` method
|
||||
|
||||
This method, which is literally *newer* -- it was added at the beginning
|
||||
of 2014 -- finally allows the API to effectively serve its intended
|
||||
purpose: incremental updates from one of the main servers to a local
|
||||
mirror.
|
||||
|
||||
- `mode` -- must be set to `newer`
|
||||
|
||||
- `timenewer` -- the API will return information on texts *modified*
|
||||
(not added) after this time, starting with the text closest to the
|
||||
specified time.
|
||||
|
||||
- `idnewer` -- the API will not return information on texts with an ID
|
||||
lower than the value of `idnewer`, even if it was modified after
|
||||
`timenewer`. (If you don't care about this parameter you can set it
|
||||
to `1`, but it is required.)
|
||||
|
||||
- `limit1` and `limit2` (optional) -- these parameters behave the same
|
||||
as they do with the grab-bag method.
|
||||
|
||||
You could use this method to display new books, but the grab-bag method
|
||||
can do that well enough for most purposes. I can't think of many uses
|
||||
for `newer` beyond its original intended one -- mirroring the main
|
||||
database.
|
||||
|
||||
#### Are you sure there's no search API?
|
||||
|
||||
Pretty sure, yeah. (There appears to be [a search API for
|
||||
Bookfi](http://genofond.org/viewtopic.php?p=22423&sid=a2cc032762a2b853b4354d287e4697e6&usg=ALkJrhjEraSeb6V9MMjk1_OCbXy2Ml_B4Q#p22423 "Russian forum post"),
|
||||
but you need to request an API key from the author.)
|
||||
|
||||
But the lack of a search API hasn't stopped people from writing scripts
|
||||
to search for and download texts from Library Genesis:
|
||||
|
||||
- A [Node.js
|
||||
module](https://www.npmjs.org/package/libgen "npm project page") by
|
||||
me
|
||||
|
||||
- A [Python
|
||||
script](https://github.com/anomico/libgen.py "GitHub repository") by
|
||||
"anomico"
|
||||
|
||||
- An [Alfred
|
||||
workflow](https://github.com/smargh/alfred_libgen "GitHub repository")
|
||||
by [Stephen Margheim](http://hackademic.postach.io)
|
||||
|
||||
- A [Chrome
|
||||
extension](https://github.com/toddpress/Looky_Booky "GitHub repository")
|
||||
by "toddpress"
|
||||
|
||||
[Let me know](https://twitter.com/dunndunndunn "Twitter") if you write
|
||||
your own!
|
236
posts/libgen.org
Normal file
236
posts/libgen.org
Normal file
|
@ -0,0 +1,236 @@
|
|||
#+TITLE: The Library Genesis API
|
||||
#+DATE: <2014-10-01 Wed>
|
||||
#+DESCRIPTION: An English-language guide to using the LibGen API.
|
||||
|
||||
[[http://libgen.io][Library Genesis]] has an API, but the only documentation is [[http://genofond.org/viewtopic.php?p=39355][a forum thread in
|
||||
Russian]]. So this is an English-language guide to using the LibGen API.
|
||||
|
||||
(I don't know Russian, and had to read the original thread using [[https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fgenofond.org%2Fviewtopic.php%3Fp%3D39355][Google
|
||||
Translate]], so corrections and additions are very welcome!)
|
||||
|
||||
* First, some bad news
|
||||
|
||||
_This is not a search API._
|
||||
|
||||
The API was apparently written to help LibGen maintainers keep their
|
||||
local mirrors up-to-date, which would explain why the API does not
|
||||
support the most common use that Library Genesis is put to by the rest
|
||||
of us: searching for texts. You can't (as far as I can tell) submit a
|
||||
string and get a list of results based on that string.
|
||||
|
||||
There are two _documented_ ways to use the API to query the LibGen
|
||||
database: by text ID, or by date.
|
||||
|
||||
* Querying by ID
|
||||
|
||||
Here's how to retrieve information about the texts with the coveted IDs
|
||||
of =1= and =2=:
|
||||
|
||||
#+BEGIN_SRC
|
||||
curl 'http://libgen.io/json.php?ids=1,2&fields=Title,Author,MD5'
|
||||
#+END_SRC
|
||||
|
||||
(The API is available at =http://gen.lib.rus.ec/json.php= as well.)
|
||||
|
||||
The above `curl` request will return an array of JSON objects:
|
||||
|
||||
#+BEGIN_SRC json
|
||||
[
|
||||
{
|
||||
"title":"Handbook of Clinical Drug Data",
|
||||
"author":"Philip Anderson",
|
||||
"md5":"7B2A4D53FDE834E801C26A2BAB7E0240"
|
||||
},
|
||||
{
|
||||
"title":"Handbook of Herbs and Spices",
|
||||
"author":"K V Peter",
|
||||
"md5":"048EA0496DB0444F873139CD705A07AF"
|
||||
}
|
||||
]
|
||||
#+END_SRC
|
||||
|
||||
I used these three fields -- =title=, =author=, and =md5= -- because
|
||||
they're all you need in most situations. You can get the page URL by
|
||||
appending the MD5 to =http://libgen.io/book/index.php?md5== or to one of
|
||||
the mirrors:
|
||||
|
||||
- =http://gen.lib.rus.ec/book/index.php?md5==
|
||||
- =http://bookzz.org/md5/=
|
||||
- =http://bookfi.org/md5/=
|
||||
|
||||
You can create a download URL by appending the MD5 to
|
||||
=http://libgen.io/get.php?md5==.
|
||||
|
||||
There are other mirrors whose URLs are based on the text's LibGen ID,
|
||||
rather than the MD5:
|
||||
|
||||
- =http://libgen.net/view.php?id==
|
||||
- =http://www.libgen.net/view.php?id==
|
||||
- =http://libgen.iofo/view.php?id==
|
||||
- =http://lib.freescienceengineering.org/view.php?id==
|
||||
|
||||
You can't get a direct download link for these; you have to go to the
|
||||
page for the text and download from there.
|
||||
|
||||
But =title=, =author=, and =md5= are far from the only available data
|
||||
fields; the full list is below. I haven't figured out what all the
|
||||
fields mean, and keep in mind that it's up to the person uploading a
|
||||
text to add this metadata, so not all texts are well-annotated.
|
||||
|
||||
- =id= -- the LibGen ID
|
||||
- =title= -- the title of the text
|
||||
- =volumeinfo= -- the volume number, if the text is part of a multi-volume series
|
||||
- =series= -- the series that the text is part of
|
||||
- =periodical=
|
||||
- =author= -- the author of the text
|
||||
- =year= -- the publication date of the text
|
||||
- =edition= -- the edition of the text
|
||||
- =publisher= -- the publisher of the text
|
||||
- =city= -- the location of the publisher
|
||||
- =pages= -- the number of pages in the text
|
||||
- =language= -- the language of the text
|
||||
- =topic= -- A number corresponding to the topic of the text; for example, =130= is "Mathematics/Logic"
|
||||
- =library=
|
||||
- =issue=
|
||||
- =identifier= -- the text's short and long [[https://www.isbn-international.org/content/what-isbn][International Standard Book Numbers]] (not necessarily in that order)
|
||||
- =issn= -- the text's [[http://www.issn.org/understanding-the-issn/what-is-an-issn/][International Standard Serial Number]]
|
||||
- =asin= -- the text's [[http://www.amazon.com/gp/seller/asin-upc-isbn-info.html][Amazon Standard Identification Number]]
|
||||
- =udc= -- the text's [[https://en.wikipedia.org/wiki/Universal_Decimal_Classification][Universal Decimal Classification]] number
|
||||
- =lbc=
|
||||
- =ddc= -- the text's [[https://en.wikipedia.org/wiki/Dewey_Decimal_Classification][Dewey Decimal Classification]] number
|
||||
- =lcc= -- the text's [[https://en.wikipedia.org/wiki/Library_of_Congress_Classification][Library of Congress Classification]] number
|
||||
- =doi= -- the file's [[https://en.wikipedia.org/wiki/Digital_object_identifier][Digital Object Identifier]]
|
||||
- =googlebookid= -- the text's [[https://developers.google.com/books/docs/v1/using#ids][Google Books ID]]
|
||||
- =openlibraryid= -- the text's [[https://openlibrary.org/dev/docs/api/books][Open Library ID]]
|
||||
- =commentary=
|
||||
- =dpi=
|
||||
- =color=
|
||||
- =cleaned=
|
||||
- =orientation=
|
||||
- =paginated= -- the text is paginated (=1=) or not (=0=)
|
||||
- =scanned= -- the text is scanned from a physical copy (=1=) or not (=0=)
|
||||
- =bookmarked= -- the text has bookmarks (=1=) or not (=0=)
|
||||
- =searchable= -- the text is searchable (=1=) or not (=0=)
|
||||
- =filesize= -- the size of the file in bytes
|
||||
- =extension= -- the extension of the file (=.pdf=, =.epub=, =.mobi=, etc.)
|
||||
- =md5= -- the [MD5](http://www.md5.net) hash of the file
|
||||
- =crc32= -- the file's [[http://www.riccibitti.com/crcguide.htm][CRC32]] checksum
|
||||
- =edonkey= -- the file's [[https://en.wikipedia.org/wiki/Ed2k_URI_scheme][eDonkey hash]]
|
||||
- =aich= -- the text's [[http://www.emule-project.net/home/perl/help.cgi?l=1&rm=show_topic&topic_id=589][eMule file hash]]
|
||||
- =sha1= -- the file's [[https://en.wikipedia.org/wiki/SHA-1][SHA-1]] hash
|
||||
- =tth= -- the file's [[https://en.wikipedia.org/wiki/Merkle_tree#Tiger_tree_hash][Tiger tree hash]]
|
||||
- =generic=
|
||||
- =filename= -- the name of the file in the LibGen database, in the
|
||||
form =directory/md5=. The directory name is the text's LibGen ID
|
||||
rounded to the nearest thousand, and the MD5 hash is in lowercase.
|
||||
(The directory that each file is located in is [[https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/util.php#L6][also included in the file name]].)
|
||||
- =visible=
|
||||
- =locator= -- [[https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/librarian/form.php#L187][As far as I can tell]], this is the file path of the original file on the machine of whoever uploaded it.
|
||||
- =local=
|
||||
- =timeadded= -- the date/time when the text was added to the database, formatted as =YYYY-MM-DD HH:MM:SS=
|
||||
- =timelastmodified= -- the date/time when the text's entry in the database was edited, formatted as =YYYY-MM-DD HH:MM:SS=
|
||||
- =coverurl= -- the path to the cover image for the text: the =filename= followed by a lowercase letter (there's [[https://github.com/lgsoft-developers/libgen/blob/c45f441c7aaa56ae690a6a6503295995a044a76b/book/util.php#L30][a function]] to determine the letter for each cover, but I don't know enough PHP to understand it).
|
||||
|
||||
If you want to get all fields for a text, use =fields=*=.
|
||||
|
||||
* Searching by date
|
||||
|
||||
Querying by ID is pretty useless except for internal tasks, so it's the
|
||||
ability to search by date that makes the API at all interesting. When
|
||||
searching by date, you don't send the =id= parameter to the API, but
|
||||
instead use some of the parameters below (along with any of the data
|
||||
fields from above):
|
||||
|
||||
- =mode= -- set to =last=, =modified=, or =newer=
|
||||
- =timefirst= -- a date formatted as =YYYY-MM-DD=
|
||||
- =timelast= -- a date formatted as =YYYY-MM-DD=
|
||||
- =timenewer= -- a time formatted as =YYYY-MM-DD%20HH:MM:SS=
|
||||
- =idnewer= -- a LibGen ID
|
||||
- =limit1= -- an integer
|
||||
- =limit2= -- an integer
|
||||
|
||||
Using these parameters allows you to do two things:
|
||||
|
||||
- +retrieve information about a random set of texts from within a
|
||||
specified date range,+ (see below) or
|
||||
|
||||
- retrieve information about texts modified after a certain time.
|
||||
|
||||
** The grab-bag method
|
||||
|
||||
+The obvious use case for this method is to display a random text or
|
||||
set of texts (perhaps for a Twitter bot).+ *I obviously didn't test
|
||||
the API enough,* because this method is _not_ random. I'll look into it
|
||||
more when I have the time.
|
||||
|
||||
The following parameters and values are allowed here:
|
||||
|
||||
- =mode= -- either =last= or =modified=. If you use =last=, the API
|
||||
will match the dates you specify against text's =timeadded=; if you
|
||||
use =modified=, it will look at =timelastmodified=.
|
||||
|
||||
- =timefirst= -- the API will not return texts before this date
|
||||
(checked against either =timeadded= or =timelastmodified= depending
|
||||
on what the =mode= is set to). The first books have a =TimeAdded=
|
||||
value of =2009-07-20=, and setting =timefirst= to an earlier date
|
||||
will return an SQL error from the API.
|
||||
|
||||
- =timelast= (optional) -- the API will not return texts after this
|
||||
date.
|
||||
|
||||
- =limit1= and =limit2= (both optional) -- if both of these parameters
|
||||
are set, the number of results returned will be the value of
|
||||
=limit2=, and the set of results will be offset by the value of
|
||||
=limit1= (not very important here, where the results are random). If
|
||||
only =limit1= is set, its value is the number of results returned.
|
||||
|
||||
Here's an example. This query returns 10 +random+ MD5 hashes for texts
|
||||
added between 1 May 2013 and 1 January 2014:
|
||||
|
||||
#+BEGIN_SRC
|
||||
curl 'http://libgen.io/json.php?fields=MD5&limit1=10&mode=last&timefirst=2013-05-01&timelast=2014-01-01'
|
||||
#+END_SRC
|
||||
|
||||
** The =newer= method
|
||||
|
||||
This method, which is literally _newer_ -- it was added at the beginning
|
||||
of 2014 -- finally allows the API to effectively serve its intended
|
||||
purpose: incremental updates from one of the main servers to a local
|
||||
mirror.
|
||||
|
||||
- =mode= -- must be set to =newer=
|
||||
|
||||
- =timenewer= -- the API will return information on texts *modified*
|
||||
(not added) after this time, starting with the text closest to the
|
||||
specified time.
|
||||
|
||||
- =idnewer= -- the API will not return information on texts with an ID
|
||||
lower than the value of =idnewer=, even if it was modified after
|
||||
=timenewer=. (If you don't care about this parameter you can set it
|
||||
to =1=, but it is required.)
|
||||
|
||||
- =limit1= and =limit2= (optional) -- these parameters behave the same
|
||||
as they do with the grab-bag method.
|
||||
|
||||
You could use this method to display new books, but the grab-bag method
|
||||
can do that well enough for most purposes. I can't think of many uses
|
||||
for =newer= beyond its original intended one -- mirroring the main
|
||||
database.
|
||||
|
||||
* Are you sure there's no search API?
|
||||
|
||||
Pretty sure, yeah. (There appears to be [[http://genofond.org/viewtopic.php?p=22423&sid=a2cc032762a2b853b4354d287e4697e6&usg=ALkJrhjEraSeb6V9MMjk1_OCbXy2Ml_B4Q#p22423][a search API for Bookfi]], but you need to
|
||||
request an API key from the author.)
|
||||
|
||||
But the lack of a search API hasn't stopped people from writing scripts
|
||||
to search for and download texts from Library Genesis:
|
||||
|
||||
- A [[https://www.npmjs.org/package/libgen][Node.js module]] by me
|
||||
|
||||
- A [[https://github.com/anomico/libgen.py][Python script]] by "anomico"
|
||||
|
||||
- An [[https://github.com/smargh/alfred_libgen][Alfred workflow]] by [Stephen Margheim](http://hackademic.postach.io)
|
||||
|
||||
- A [[https://github.com/toddpress/Looky_Booky][Chrome extension]] by "toddpress"
|
||||
|
||||
[[https://twitter.com/dunndunndunn][Let me know]] if you write your own!
|
|
@ -1,27 +1,22 @@
|
|||
---
|
||||
title: The Hardest Problem In Computer Science is Opening a Port
|
||||
date: 2020-06-09
|
||||
description: Or, how to get RTMP working in Kubernetes.
|
||||
layout: layouts/post.njk
|
||||
tags: post
|
||||
---
|
||||
#+TITLE: The Hardest Problem In Computer Science is Opening a Port
|
||||
#+DATE: <2020-06-09 Tue>
|
||||
#+DESCRIPTION: Or, how to get RTMP working in Kubernetes.
|
||||
|
||||
All I wanted was to open port 1935 so that I could run my
|
||||
[MovieNight](https://github.com/zorchenhimer/MovieNight) instance in a cluster.
|
||||
But I couldn’t find anywhere describing all the steps to actually open a port on
|
||||
Kubernetes. But #ShePersisted or whatever.
|
||||
All I wanted was to open port 1935 so that I could run my [[https://github.com/zorchenhimer/MovieNight][MovieNight]] instance in
|
||||
a cluster. But I couldn’t find anywhere describing all the steps to actually
|
||||
open a port on Kubernetes. But #ShePersisted or whatever.
|
||||
|
||||
**NB:** a non-http port (like 1935 for RTMP, or 21 for FTP, or) can only be made
|
||||
accessible to one (1) service in your entire cluster. So choose wisely. Yes,
|
||||
this is batshit.
|
||||
|
||||
## Configuration the Application
|
||||
* Configuration the Application
|
||||
|
||||
If you’re deploying your application with a Helm chart, make sure that its
|
||||
service type is NodePort, and specify each port you want accessible in its
|
||||
`service.yaml`:
|
||||
=service.yaml=:
|
||||
|
||||
```yaml
|
||||
#+BEGIN_SRC yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
|
@ -41,12 +36,13 @@ spec:
|
|||
name: rtmp
|
||||
selector:
|
||||
{{- include "movienight.selectorLabels" . | nindent 4 }}
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
List the same additional ports in your application’s `deployment.yaml` (here
|
||||
8089 is what we are exposing as port 80, since that’s what MovieNight binds to
|
||||
by default):
|
||||
```yaml
|
||||
List the same additional ports in your application’s =deployment.yaml=
|
||||
(here 8089 is what we are exposing as port 80, since that’s what MovieNight
|
||||
binds to by default):
|
||||
|
||||
#+BEGIN_SRC yaml
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
|
@ -60,12 +56,13 @@ by default):
|
|||
- name: rtmp
|
||||
containerPort: 1935
|
||||
protocol: TCP
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
## Configure the Ingress Controller
|
||||
* Configure the Ingress Controller
|
||||
|
||||
Find your ingress controller service and deployments in the cluster:
|
||||
```text
|
||||
|
||||
#+BEGIN_SRC
|
||||
$ kubectl get all
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
|
@ -81,54 +78,53 @@ deployment.apps/ingress-ingress-nginx-controller 1/1 1 1
|
|||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/ingress-ingress-nginx-controller-7555b9d446 1 1 1 89s
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
To open port 1935 like you see above, first edit the deployment definition:
|
||||
```text
|
||||
|
||||
#+BEGIN_SRC
|
||||
kubectl edit deployment.apps/ingress-ingress-nginx-controller
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
And add two things:
|
||||
|
||||
1. in `spec.containers.ports`, add the port you want open (I want 1935, which is
|
||||
RTMP):
|
||||
```yaml
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
name: https
|
||||
protocol: TCP
|
||||
- containerPort: 1935
|
||||
name: rtmp
|
||||
protocol: TCP
|
||||
- containerPort: 8443
|
||||
name: webhook
|
||||
protocol: TCP
|
||||
```
|
||||
1. in =spec.containers.ports=, add the port you want open (I want 1935, which is
|
||||
RTMP):
|
||||
#+BEGIN_SRC yaml
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
name: https
|
||||
protocol: TCP
|
||||
- containerPort: 1935
|
||||
name: rtmp
|
||||
protocol: TCP
|
||||
- containerPort: 8443
|
||||
name: webhook
|
||||
protocol: TCP
|
||||
#+END_SRC
|
||||
2. in =spec.containers.args=, add a line for [[https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/][=tcp-services-configmap=]]:
|
||||
#+BEGIN_SRC yaml
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- /nginx-ingress-controller
|
||||
- --publish-service=default/ingress-ingress-nginx-controller
|
||||
- --election-id=ingress-controller-leader
|
||||
- --ingress-class=nginx
|
||||
- --configmap=default/ingress-ingress-nginx-controller
|
||||
- --tcp-services-configmap=default/tcp-services
|
||||
- --validating-webhook=:8443
|
||||
- --validating-webhook-certificate=/usr/local/certificates/cert
|
||||
- --validating-webhook-key=/usr/local/certificates/key
|
||||
#+END_SRC
|
||||
|
||||
2. in `spec.containers.args`, add a line for
|
||||
[`tcp-services-configmap`](https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/):
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- /nginx-ingress-controller
|
||||
- --publish-service=default/ingress-ingress-nginx-controller
|
||||
- --election-id=ingress-controller-leader
|
||||
- --ingress-class=nginx
|
||||
- --configmap=default/ingress-ingress-nginx-controller
|
||||
- --tcp-services-configmap=default/tcp-services
|
||||
- --validating-webhook=:8443
|
||||
- --validating-webhook-certificate=/usr/local/certificates/cert
|
||||
- --validating-webhook-key=/usr/local/certificates/key
|
||||
```
|
||||
|
||||
`default/tcp-services` refers to the namespace and name of the ConfigMap you’re
|
||||
=default/tcp-services= refers to the namespace and name of the ConfigMap you’re
|
||||
about to create:
|
||||
|
||||
```yaml
|
||||
#+BEGIN_SRC yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
|
@ -137,25 +133,27 @@ metadata:
|
|||
namespace: default
|
||||
data:
|
||||
1935: "movienight/trashcloud-movienight:1935"
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
Here `movienight/trashcloud-movienight` refers to the namespace and service name
|
||||
of your application.
|
||||
Here =movienight/trashcloud-movienight= refers to the namespace and
|
||||
service name of your application.
|
||||
|
||||
Install your ConfigMap:
|
||||
```text
|
||||
|
||||
#+BEGIN_SRC
|
||||
kubectl apply -f tcp-services.yaml
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
Then, edit the service definition of the ingress controller:
|
||||
```text
|
||||
kubectl edit service/ingress-ingress-nginx-controller
|
||||
```
|
||||
|
||||
In `spec.ports`, add an entry for the new port, and assign it an unused
|
||||
[NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#nodeport)
|
||||
between 30000 and 32767:
|
||||
```yaml
|
||||
#+BEGIN_SRC
|
||||
kubectl edit service/ingress-ingress-nginx-controller
|
||||
#+END_SRC
|
||||
|
||||
In =spec.ports=, add an entry for the new port, and assign it an unused
|
||||
[[https://kubernetes.io/docs/concepts/services-networking/service/#nodeport][NodePort]] between 30000 and 32767:
|
||||
|
||||
#+BEGIN_SRC yaml
|
||||
spec:
|
||||
clusterIP: 10.128.94.66
|
||||
externalTrafficPolicy: Cluster
|
||||
|
@ -175,7 +173,7 @@ spec:
|
|||
port: 1935
|
||||
protocol: TCP
|
||||
targetPort: 1935
|
||||
```
|
||||
#+END_SRC
|
||||
|
||||
And that should do it! I’m very sleep deprived on account of this nonsense so
|
||||
if I’ve forgotten a step let me know.
|
28
publish.el
Normal file
28
publish.el
Normal file
|
@ -0,0 +1,28 @@
|
|||
(require 'package)
|
||||
(package-initialize)
|
||||
(add-to-list 'package-archives
|
||||
'("melpa" . "https://melpa.org/packages/") t)
|
||||
(package-refresh-contents)
|
||||
|
||||
(require 'org)
|
||||
(require 'org-static-blog)
|
||||
|
||||
(let ((org-static-blog-publish-title "GARBAGE WORLD")
|
||||
(org-static-blog-publish-url "")
|
||||
(org-static-blog-publish-directory "")
|
||||
(org-static-blog-posts-directory "posts/")
|
||||
(org-static-blog-drafts-directory "drafts/")
|
||||
(org-static-blog-enable-tags nil)
|
||||
(org-export-with-toc nil)
|
||||
(org-export-with-section-numbers nil)
|
||||
(org-static-blog-page-header
|
||||
"<meta charset=\"utf-8\">
|
||||
<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">
|
||||
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />
|
||||
<link href=\"stylesheets/screen.css\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />
|
||||
<link href=\"stylesheets/print.css\" rel=\"stylesheet\" type=\"text/css\" media=\"print\" />")
|
||||
(org-static-blog-page-preamble
|
||||
"<header>
|
||||
<h1><a href=\"/\" title=\"root\">🖥😩</a></h1>
|
||||
</header>"))
|
||||
(org-static-blog-publish t))
|
|
@ -31,6 +31,15 @@ aside {
|
|||
}
|
||||
}
|
||||
|
||||
.post-date {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 5px solid black;
|
||||
margin: 1em;
|
||||
|
@ -46,6 +55,12 @@ footer {
|
|||
min-width: 20%;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #1e1e1e;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
8
setup.el
Normal file
8
setup.el
Normal file
|
@ -0,0 +1,8 @@
|
|||
(require 'package)
|
||||
(package-initialize)
|
||||
(add-to-list 'package-archives
|
||||
'("melpa" . "https://melpa.org/packages/") t)
|
||||
(package-refresh-contents)
|
||||
|
||||
(package-install 'org)
|
||||
(package-install 'org-static-blog)
|
|
@ -1,2 +0,0 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
|
||||
/*# sourceMappingURL=normalize-8.0.1.css.map */
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAAA,4EAA4E,AAU5E,IAAK,CACH,WAAW,CAAE,IAAI,CACjB,wBAAwB,CAAE,IAAI,CAUhC,IAAK,CACH,MAAM,CAAE,CAAC,CAOX,IAAK,CACH,OAAO,CAAE,KAAK,CAQhB,EAAG,CACD,SAAS,CAAE,GAAG,CACd,MAAM,CAAE,QAAQ,CAWlB,EAAG,CACD,UAAU,CAAE,WAAW,CACvB,MAAM,CAAE,CAAC,CACT,QAAQ,CAAE,OAAO,CAQnB,GAAI,CACF,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAUhB,CAAE,CACA,gBAAgB,CAAE,WAAW,CAQ/B,WAAY,CACV,aAAa,CAAE,IAAI,CACnB,eAAe,CAAE,SAAS,CAC1B,eAAe,CAAE,gBAAgB,CAOnC,QACO,CACL,WAAW,CAAE,MAAM,CAQrB,aAEK,CACH,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAOhB,KAAM,CACJ,SAAS,CAAE,GAAG,CAQhB,OACI,CACF,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,CAAC,CACd,QAAQ,CAAE,QAAQ,CAClB,cAAc,CAAE,QAAQ,CAG1B,GAAI,CACF,MAAM,CAAE,OAAO,CAGjB,GAAI,CACF,GAAG,CAAE,MAAM,CAUb,GAAI,CACF,YAAY,CAAE,IAAI,CAWpB,qCAIS,CACP,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,IAAI,CACjB,MAAM,CAAE,CAAC,CAQX,YACM,CACJ,QAAQ,CAAE,OAAO,CAQnB,aACO,CACL,cAAc,CAAE,IAAI,CAOtB,qDAGgB,CACd,kBAAkB,CAAE,MAAM,CAO5B,6HAGkC,CAChC,YAAY,CAAE,IAAI,CAClB,OAAO,CAAE,CAAC,CAOZ,iHAG+B,CAC7B,OAAO,CAAE,qBAAqB,CAOhC,QAAS,CACP,OAAO,CAAE,qBAAqB,CAUhC,MAAO,CACL,UAAU,CAAE,UAAU,CACtB,KAAK,CAAE,OAAO,CACd,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,MAAM,CAOrB,QAAS,CACP,cAAc,CAAE,QAAQ,CAO1B,QAAS,CACP,QAAQ,CAAE,IAAI,CAQhB,gCACe,CACb,UAAU,CAAE,UAAU,CACtB,OAAO,CAAE,CAAC,CAOZ,qFAC2C,CACzC,MAAM,CAAE,IAAI,CAQd,eAAgB,CACd,kBAAkB,CAAE,SAAS,CAC7B,cAAc,CAAE,IAAI,CAOtB,0CAA2C,CACzC,kBAAkB,CAAE,IAAI,CAQ1B,4BAA6B,CAC3B,kBAAkB,CAAE,MAAM,CAC1B,IAAI,CAAE,OAAO,CAUf,OAAQ,CACN,OAAO,CAAE,KAAK,CAOhB,OAAQ,CACN,OAAO,CAAE,SAAS,CAUpB,QAAS,CACP,OAAO,CAAE,IAAI,CAOf,QAAS,CACP,OAAO,CAAE,IAAI",
|
||||
"sources": ["../sass/normalize-8.0.1.scss"],
|
||||
"names": [],
|
||||
"file": "normalize-8.0.1.css"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
|
||||
/*# sourceMappingURL=print.css.map */
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAAA,4EAA4E,AAU5E,IAAK,CACH,WAAW,CAAE,IAAI,CACjB,wBAAwB,CAAE,IAAI,CAUhC,IAAK,CACH,MAAM,CAAE,CAAC,CAOX,IAAK,CACH,OAAO,CAAE,KAAK,CAQhB,EAAG,CACD,SAAS,CAAE,GAAG,CACd,MAAM,CAAE,QAAQ,CAWlB,EAAG,CACD,UAAU,CAAE,WAAW,CACvB,MAAM,CAAE,CAAC,CACT,QAAQ,CAAE,OAAO,CAQnB,GAAI,CACF,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAUhB,CAAE,CACA,gBAAgB,CAAE,WAAW,CAQ/B,WAAY,CACV,aAAa,CAAE,IAAI,CACnB,eAAe,CAAE,SAAS,CAC1B,eAAe,CAAE,gBAAgB,CAOnC,QACO,CACL,WAAW,CAAE,MAAM,CAQrB,aAEK,CACH,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAOhB,KAAM,CACJ,SAAS,CAAE,GAAG,CAQhB,OACI,CACF,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,CAAC,CACd,QAAQ,CAAE,QAAQ,CAClB,cAAc,CAAE,QAAQ,CAG1B,GAAI,CACF,MAAM,CAAE,OAAO,CAGjB,GAAI,CACF,GAAG,CAAE,MAAM,CAUb,GAAI,CACF,YAAY,CAAE,IAAI,CAWpB,qCAIS,CACP,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,IAAI,CACjB,MAAM,CAAE,CAAC,CAQX,YACM,CACJ,QAAQ,CAAE,OAAO,CAQnB,aACO,CACL,cAAc,CAAE,IAAI,CAOtB,qDAGgB,CACd,kBAAkB,CAAE,MAAM,CAO5B,6HAGkC,CAChC,YAAY,CAAE,IAAI,CAClB,OAAO,CAAE,CAAC,CAOZ,iHAG+B,CAC7B,OAAO,CAAE,qBAAqB,CAOhC,QAAS,CACP,OAAO,CAAE,qBAAqB,CAUhC,MAAO,CACL,UAAU,CAAE,UAAU,CACtB,KAAK,CAAE,OAAO,CACd,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,MAAM,CAOrB,QAAS,CACP,cAAc,CAAE,QAAQ,CAO1B,QAAS,CACP,QAAQ,CAAE,IAAI,CAQhB,gCACe,CACb,UAAU,CAAE,UAAU,CACtB,OAAO,CAAE,CAAC,CAOZ,qFAC2C,CACzC,MAAM,CAAE,IAAI,CAQd,eAAgB,CACd,kBAAkB,CAAE,SAAS,CAC7B,cAAc,CAAE,IAAI,CAOtB,0CAA2C,CACzC,kBAAkB,CAAE,IAAI,CAQ1B,4BAA6B,CAC3B,kBAAkB,CAAE,MAAM,CAC1B,IAAI,CAAE,OAAO,CAUf,OAAQ,CACN,OAAO,CAAE,KAAK,CAOhB,OAAQ,CACN,OAAO,CAAE,SAAS,CAUpB,QAAS,CACP,OAAO,CAAE,IAAI,CAOf,QAAS,CACP,OAAO,CAAE,IAAI",
|
||||
"sources": ["../sass/normalize-8.0.1.scss"],
|
||||
"names": [],
|
||||
"file": "print.css"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}*,*:before,*:after{box-sizing:border-box}body{font-family:monospace;font-size:14pt;padding:0 1em}header{padding:1em;text-align:right}header h1,header h2{margin:0}header h2,aside h2{font-style:italic}img{border:5px solid black;margin:1em;width:100%}article+article{padding-top:2em}aside,footer{min-width:20%}dt{font-weight:bold}h1{font-size:225%}h2{font-size:150%}h3{font-size:131.25%}h4,h5,h6{font-size:112.5%}h5,h6{font-style:italic}h6{font-weight:normal}
|
||||
/*# sourceMappingURL=screen.css.map */
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAAA,4EAA4E,AAU5E,IAAK,CACH,WAAW,CAAE,IAAI,CACjB,wBAAwB,CAAE,IAAI,CAUhC,IAAK,CACH,MAAM,CAAE,CAAC,CAOX,IAAK,CACH,OAAO,CAAE,KAAK,CAQhB,EAAG,CACD,SAAS,CAAE,GAAG,CACd,MAAM,CAAE,QAAQ,CAWlB,EAAG,CACD,UAAU,CAAE,WAAW,CACvB,MAAM,CAAE,CAAC,CACT,QAAQ,CAAE,OAAO,CAQnB,GAAI,CACF,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAUhB,CAAE,CACA,gBAAgB,CAAE,WAAW,CAQ/B,WAAY,CACV,aAAa,CAAE,IAAI,CACnB,eAAe,CAAE,SAAS,CAC1B,eAAe,CAAE,gBAAgB,CAOnC,QACO,CACL,WAAW,CAAE,MAAM,CAQrB,aAEK,CACH,WAAW,CAAE,oBAAoB,CACjC,SAAS,CAAE,GAAG,CAOhB,KAAM,CACJ,SAAS,CAAE,GAAG,CAQhB,OACI,CACF,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,CAAC,CACd,QAAQ,CAAE,QAAQ,CAClB,cAAc,CAAE,QAAQ,CAG1B,GAAI,CACF,MAAM,CAAE,OAAO,CAGjB,GAAI,CACF,GAAG,CAAE,MAAM,CAUb,GAAI,CACF,YAAY,CAAE,IAAI,CAWpB,qCAIS,CACP,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,IAAI,CACjB,MAAM,CAAE,CAAC,CAQX,YACM,CACJ,QAAQ,CAAE,OAAO,CAQnB,aACO,CACL,cAAc,CAAE,IAAI,CAOtB,qDAGgB,CACd,kBAAkB,CAAE,MAAM,CAO5B,6HAGkC,CAChC,YAAY,CAAE,IAAI,CAClB,OAAO,CAAE,CAAC,CAOZ,iHAG+B,CAC7B,OAAO,CAAE,qBAAqB,CAOhC,QAAS,CACP,OAAO,CAAE,qBAAqB,CAUhC,MAAO,CACL,UAAU,CAAE,UAAU,CACtB,KAAK,CAAE,OAAO,CACd,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,MAAM,CAOrB,QAAS,CACP,cAAc,CAAE,QAAQ,CAO1B,QAAS,CACP,QAAQ,CAAE,IAAI,CAQhB,gCACe,CACb,UAAU,CAAE,UAAU,CACtB,OAAO,CAAE,CAAC,CAOZ,qFAC2C,CACzC,MAAM,CAAE,IAAI,CAQd,eAAgB,CACd,kBAAkB,CAAE,SAAS,CAC7B,cAAc,CAAE,IAAI,CAOtB,0CAA2C,CACzC,kBAAkB,CAAE,IAAI,CAQ1B,4BAA6B,CAC3B,kBAAkB,CAAE,MAAM,CAC1B,IAAI,CAAE,OAAO,CAUf,OAAQ,CACN,OAAO,CAAE,KAAK,CAOhB,OAAQ,CACN,OAAO,CAAE,SAAS,CAUpB,QAAS,CACP,OAAO,CAAE,IAAI,CAOf,QAAS,CACP,OAAO,CAAE,IAAI,CCvVf,kBAEQ,CACN,UAAU,CAAE,UAAU,CAGxB,IAAK,CACH,WAAW,CAAE,SAAS,CACtB,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,KAAK,CAGhB,MAAO,CACL,OAAO,CAAE,GAAG,CACZ,UAAU,CAAE,KAAK,CAEjB,mBACG,CACD,MAAM,CAAE,CAAC,CAMX,kBAAG,CACD,UAAU,CAAE,MAAM,CAItB,GAAI,CACF,MAAM,CAAE,eAAe,CACvB,MAAM,CAAE,GAAG,CACX,KAAK,CAAE,IAAI,CAGb,eAAkB,CAChB,WAAW,CAAE,GAAG,CAGlB,YACO,CACL,SAAS,CAAE,GAAG,CAGhB,EAAG,CACD,WAAW,CAAE,IAAI,CAGnB,EAAG,CACD,SAAS,CAAE,IAAI,CAGjB,EAAG,CACD,SAAS,CAAE,IAAI,CAGjB,EAAG,CACD,SAAS,CAAE,OAAO,CAGpB,QAEG,CACD,SAAS,CAAE,MAAM,CAGnB,KACG,CACD,UAAU,CAAE,MAAM,CAGpB,EAAG,CACD,WAAW,CAAE,MAAM",
|
||||
"sources": ["../sass/normalize-8.0.1.scss","../sass/screen.scss"],
|
||||
"names": [],
|
||||
"file": "screen.css"
|
||||
}
|
Loading…
Reference in a new issue