README.md

  1<!--
  2SPDX-FileCopyrightText: 2022 Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: CC0-1.0
  5-->
  6
  7# earl
  8
  9[![REUSE status][reuse-shield]][reuse]
 10[![Donate with fosspay][fosspay-shield]][fosspay]
 11![Time spent on project][wakapi-shield]
 12
 13Personal shortlink generator
 14
 15## Features
 16
 17Links are …
 18
 19- Editable
 20- Removable
 21- Four characters long (26 uppercase letters + 26 lowercase letters + 10 numbers
 22  = 14,776,336 possible shortened URLs)
 23
 24Service has …
 25
 26- A simple API
 27- A simple web UI
 28- A simple backup procedure (database is a single directory)
 29- No user management (this is a _personal_ service after all)
 30
 31## API documentation
 32
 33### `/create`
 34
 35#### Required parameters
 36
 37- `url`: percent-encoded URL being shortened
 38
 39#### Optional parameters
 40
 41- `name`: percent-encoded short link the `url` will be mapped to. If this is not
 42  provided, a random, 4-character code will be generated instead.
 43
 44#### Output
 45
 46- `401 Unauthorized: You do not have permission to create shortlinks` if access
 47  token provided in `Authorization` header does not match the configured access
 48  token
 49- `400 Bad Request: URL parameter is required`
 50- `406 Not Acceptable: A shortened URL with this name already exists` if
 51  provided name already exists in the database
 52- `URL mapped to $NAME` (200 OK)
 53
 54### `/read`
 55
 56#### Required parameters
 57
 58- None
 59
 60#### Optional parameters
 61
 62- None
 63
 64#### Output
 65
 66- `401 Unauthorized: You do not have permission to view shortlinks` if access
 67  token provided in `Authorization` header does not match the configured access
 68  token
 69- JSON representation of the key/value database (200 OK)
 70  ```json
 71  {
 72    "6H1g": "https://git.sr.ht/~amolith/earl/tree/dev",
 73    "N3yg": "https://secluded.site/"
 74  }
 75  ```
 76
 77### `/update`
 78
 79#### Required parameters:
 80
 81- `oldName`: percent-encoded name the URL is _currently_ referred to with
 82- `name`: percent-encoded name the URL _will_ be referred to with
 83- `url`: percent-encoded URL being shortened
 84
 85`name` and `url` are first set as a key/value pair. If `name` already exists,
 86`url` is updated. If `name` does _not_ already exist, it's created and `oldName`
 87is deleted. If the user is only modifying `url`, `oldName` and `name` should
 88both be submitted but their values should be identical.
 89
 90#### Optional parameters:
 91
 92- None
 93
 94#### Output:
 95
 96- `401 Unauthorized: You do not have permission to create shortlinks` if access
 97  token provided in `Authorization` header does not match the configured access
 98  token
 99- `400 Bad Request: oldName parameter is required`
100- `400 Bad Request: name parameter is required`
101- `400 Bad Request: URL parameter is required`
102- `406 Not Acceptable: A shortened URL with this name already exists` if
103  provided name already exists in the database
104- `$URL mapped to $NAME` (200 OK)
105
106### `/delete`
107
108#### Required parameters:
109
110- `name`: percent-encoded short link
111
112#### Optional parameters:
113
114- None
115
116#### Output:
117
118- `401 Unauthorized: You do not have permission to create shortlinks` if access
119  token provided in `Authorization` header does not match the configured access
120  token
121- `400 Bad Request: name parameter is required`
122- `$URL has been deleted` (200 OK)
123
124## But … why?
125
126Good question. URL shorteners are (usually) terrible and useless. Except when
127used correctly :thinkingsmart:
128
129I take a lot of hand-written notes on things and, having both a passion for and
130job in IT, my notes would be much more useful if they included links to the
131things I'm writing about. However, there's no way I'm going to hand-write a 50+
132character URL.
133
134That's where URL shorteners come in!
135
136Most shortener services I've found that are both open source and self-hosted use
137something like 6-character-long paths for the links as they're meant for use by
138multiple people; 14.8m possible URLs (your cap with 4 character paths) aren't
139enough for public services.
140
141Now six characters is _fine_ but why write six characters when you could write
142four :D
143
144And why deal with user management and a relational database when you're only
145going to have one user and a bunch of keys with values :D
146
147I was also unsatisfied with the tech stack and feature sets of the alternatives;
148they were all either a pain to set up and update or they had click counters and
149link tracking and a bunch of other crap I have no use for.
150
151So I decided to make my own that has exactly what I want and nothing more :D
152
153## Questions & Contributions
154
155Questions, comments, and patches can always be sent to my public inbox, but I'm
156also in my IRC channel/XMPP room pretty much 24/7. However, I might not see
157messages right away because I'm working on something else (or sleeping) so
158please stick around!
159
160If you're wanting to introduce a new feature and I don't feel like it fits with
161this project's goal, I encourage you to fork the repo and make whatever changes
162you like!
163
164- Email: [~amolith/public-inbox@lists.sr.ht][email]
165- IRC: [irc.nixnet.services/#secluded][irc]
166- XMPP: [secluded@muc.secluded.site][xmpp]
167
168_If you haven't used mailing lists before, please take a look at [SourceHut's
169documentation](https://man.sr.ht/lists.sr.ht/), especially the etiquette
170section._
171
172[reuse]: https://api.reuse.software/info/git.sr.ht/~amolith/earl
173[reuse-shield]: https://shields.io/reuse/compliance/git.sr.ht/~amolith/earl
174[fosspay]: https://secluded.site/donate/
175[fosspay-shield]: https://shields.io/badge/donate-fosspay-yellow
176[wakapi-shield]: https://img.shields.io/endpoint?url=https://waka.secluded.site/api/compat/shields/v1/amolith/interval:any/project:earl&color=blue&label=time%20spent
177[email]: mailto:~amolith/public-inbox@lists.sr.ht
178[irc]: irc://irc.nixnet.services/#secluded
179[xmpp]: xmpp:secluded@muc.secluded.site?join