mirror of https://github.com/miniflux/v2.git
Compare commits
646 Commits
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 84e97826d8 | |
x | 839fc3843a | |
x | 0bab8fac8e | |
dependabot[bot] | 0cf1a40276 | |
dependabot[bot] | 91479bc0ee | |
dependabot[bot] | 251821289c | |
dependabot[bot] | cac0bc682f | |
dependabot[bot] | a733c14c61 | |
Ankit Pandey | b68b05c64c | |
Frédéric Guillot | 5ce3f24838 | |
dependabot[bot] | 48ddc02ba8 | |
dependabot[bot] | fe9f1bba16 | |
Krish Mamtora | 740fa4a5d2 | |
dependabot[bot] | 8a38f54ef5 | |
Zhizhen He | ae432bc9c6 | |
dependabot[bot] | 96f7e8bae0 | |
rootknight | 1f35ed1675 | |
dependabot[bot] | d6deac1810 | |
Frédéric Guillot | b692768730 | |
dependabot[bot] | 2178580a75 | |
dependabot[bot] | b52f61cc77 | |
dependabot[bot] | 3388f8e376 | |
dependabot[bot] | 83ceb20c1c | |
dependabot[bot] | c06850ca34 | |
dependabot[bot] | d856c02fbb | |
Jan-Lukas Else | a33b1adf13 | |
fin444 | a631bd527d | |
Alpha Chen | ca62b0b36b | |
Kioubit | 7d6a4243c1 | |
dependabot[bot] | d056aa1f73 | |
dependabot[bot] | 018e24404e | |
Frédéric Guillot | 4d3ee0d15d | |
Frédéric Guillot | 797450986b | |
Ztec | 93bc9ce24d | |
dependabot[bot] | 9233568da3 | |
Frédéric Guillot | fb075b60b5 | |
Frédéric Guillot | 2c4c845cd2 | |
bo0tzz | 2caabbe939 | |
Frédéric Guillot | 771f9d2b5f | |
Romain de Laage | 647c66e70a | |
jvoisin | b205b5aad0 | |
goodfirm | 4ab0d9422d | |
Frédéric Guillot | 38b80d96ea | |
Michael Kuhn | 35edd8ea92 | |
Alexandros Kosiaris | f0cb041885 | |
Frédéric Guillot | fdd1b3f18e | |
Frédéric Guillot | 6e870cdccc | |
Michael Kuhn | 194f517be8 | |
dependabot[bot] | 11fd1c935e | |
dependabot[bot] | 47e1111908 | |
dependabot[bot] | c5b812eb7b | |
dependabot[bot] | 53be550e8a | |
dependabot[bot] | d0d693a6ef | |
Evan Elias Young | 1b8c45d162 | |
jvoisin | 19ce519836 | |
Thomas J Faughnan Jr | 3e0d5de7a3 | |
Frédéric Guillot | 0336774e8c | |
Jean Khawand | 756dd449cc | |
Taylan Tatlı | a0b4665080 | |
dependabot[bot] | 6592c1ad6b | |
jvoisin | f109e3207c | |
Romain de Laage | b54fe66809 | |
jvoisin | 93c9d43497 | |
Frédéric Guillot | e3b3c40c28 | |
Frédéric Guillot | 068790fc19 | |
Frédéric Guillot | 41d99c517f | |
Frédéric Guillot | 3db3f9884f | |
Frédéric Guillot | ad1d349a0c | |
Jean Khawand | 7ee4a731af | |
Jean Khawand | 3c822a45ac | |
Frédéric Guillot | c2311e316c | |
jvoisin | ed20771194 | |
jvoisin | beb8c80787 | |
jvoisin | fc4bdf3ab0 | |
Frédéric Guillot | 6bc819e198 | |
Frédéric Guillot | 08640b27d5 | |
jvoisin | 4be993e055 | |
jvoisin | 9df12177eb | |
Jean Khawand | a78d1c79da | |
Matt Behrens | 1ea3953271 | |
dependabot[bot] | fe8b7a907e | |
Frédéric Guillot | a15cdb1655 | |
Frédéric Guillot | fa9697b972 | |
jvoisin | 8e28e41b02 | |
jvoisin | e2ee74428a | |
jvoisin | 863a5b3648 | |
jvoisin | 91f5522ce0 | |
Frédéric Guillot | 8212f16aa2 | |
Frédéric Guillot | b1e73fafdf | |
Frédéric Guillot | f6404290ba | |
jvoisin | c29ca0e313 | |
jvoisin | 02a074ed26 | |
Romain de Laage | 00dabc1d3c | |
Frédéric Guillot | b68ada396a | |
Frédéric Guillot | e299e821a6 | |
Frédéric Guillot | 0f17dfc7d6 | |
Frédéric Guillot | 7c80d6b86d | |
Frédéric Guillot | f6f63b5282 | |
Frédéric Guillot | 309fdbb9fc | |
Frédéric Guillot | e2d862f2f6 | |
Frédéric Guillot | 4834e934f2 | |
Frédéric Guillot | dd4fb660c1 | |
jvoisin | 2ba893bc79 | |
Frédéric Guillot | 7a307f8e74 | |
jvoisin | 7310e13499 | |
dependabot[bot] | bf6d286735 | |
Frédéric Guillot | ca919c2ff8 | |
Frédéric Guillot | 5948786b15 | |
jvoisin | f4746a7306 | |
Frédéric Guillot | 648b9a8f6f | |
jvoisin | 66b8483791 | |
jvoisin | e0ee28c013 | |
dependabot[bot] | d862d86f90 | |
jvoisin | d25c032171 | |
Frédéric Guillot | 8429c6b0ab | |
Frédéric Guillot | 6bc4b35e38 | |
mcnesium | ee3486af66 | |
jvoisin | 45d486b919 | |
dependabot[bot] | 688b73b7ae | |
Frédéric Guillot | 6d97f8b458 | |
Frédéric Guillot | f8e50947f2 | |
Frédéric Guillot | 9a637ce95e | |
Frédéric Guillot | d3a85b049b | |
jvoisin | 5bcb37901c | |
jvoisin | 9c8a7dfffe | |
jvoisin | 74e4032ffc | |
jvoisin | fd1fee852c | |
Frédéric Guillot | c51a3270da | |
Frédéric Guillot | 45fa641d26 | |
jvoisin | fd8f25916b | |
jvoisin | 826e4d654f | |
jvoisin | d9d17f0d69 | |
Frédéric Guillot | eaaeb68474 | |
Frédéric Guillot | 382885f144 | |
dependabot[bot] | 0f7b047b0a | |
jvoisin | a074773e6c | |
jvoisin | 3d0126be0b | |
dependabot[bot] | eda2e2f3f5 | |
jvoisin | 111e3f2106 | |
dependabot[bot] | c1ec77a42c | |
jvoisin | 3339d9d3d7 | |
jvoisin | 8d80e9103f | |
jvoisin | d55b410800 | |
jvoisin | 9fe99ce7fa | |
Thiago Perrotta | b8df6c31a0 | |
Frédéric Guillot | abdd5876a1 | |
Frédéric Guillot | 1b5edfc00a | |
jvoisin | 347740dce1 | |
jvoisin | ab85d4d678 | |
jvoisin | 31ac62f410 | |
Frédéric Guillot | 97765b93a9 | |
dependabot[bot] | f858ad5f26 | |
jvoisin | e6524f925f | |
Frédéric Guillot | c493f8921e | |
Frédéric Guillot | b2ce98da87 | |
jvoisin | 4db138d4b8 | |
jvoisin | f12d5131b0 | |
jvoisin | 1f5c8ce353 | |
jvoisin | 645a817685 | |
jvoisin | f4f8342245 | |
jvoisin | 543a690bfd | |
jvoisin | c4e5dad549 | |
jvoisin | fa12c23d79 | |
jvoisin | 4fe902a5d2 | |
jvoisin | 61af08a721 | |
jvoisin | b04550e2f2 | |
jvoisin | 5e5cb056c5 | |
jvoisin | 48fa64f8ec | |
jvoisin | f274394f0e | |
jvoisin | 9a4a942cc4 | |
jvoisin | 6b3b8e8c9b | |
jvoisin | 5a7d6f8997 | |
jvoisin | b4ed17fbac | |
dependabot[bot] | 57476f4d59 | |
jvoisin | 7660910232 | |
jvoisin | b054506e3a | |
jvoisin | c961c6db7d | |
Frédéric Guillot | 0f126d4d11 | |
jvoisin | b94756bbf0 | |
jvoisin | db6ae707ef | |
Frédéric Guillot | 97feec8ebf | |
jvoisin | bce21a9f91 | |
jvoisin | 06e256e5ef | |
jvoisin | 040938ff6d | |
dependabot[bot] | 21da7f77f5 | |
jvoisin | c2d2f31438 | |
jvoisin | 5b2558bf92 | |
jvoisin | ecd59009fb | |
jvoisin | 4a943b722d | |
Frédéric Guillot | 9d1b1e19d4 | |
Frédéric Guillot | 7a8061fc72 | |
jvoisin | bca84bac8b | |
jvoisin | 66e0eb1bd6 | |
jvoisin | 26d189917e | |
jvoisin | ccd3955bf4 | |
jvoisin | 8a2cc3a344 | |
jvoisin | 647fa025f8 | |
jvoisin | 1955350318 | |
jvoisin | 04916a57d2 | |
jvoisin | 0adac5c6f7 | |
jvoisin | 54b5be5e7d | |
Frédéric Guillot | eae4cb1417 | |
Frédéric Guillot | 420a3d4d95 | |
jvoisin | b48ad6dbfb | |
jvoisin | 2be5051b19 | |
jvoisin | c544dadd55 | |
Frédéric Guillot | 1da65d97d8 | |
Frédéric Guillot | c595c80356 | |
dependabot[bot] | 20e5fbcd7a | |
dependabot[bot] | ac77154907 | |
Thomas J Faughnan Jr | 97ace53bc9 | |
Frédéric Guillot | feb962f98a | |
Frédéric Guillot | 8602089a1e | |
Frédéric Guillot | 4b0648f3d7 | |
Frédéric Guillot | 856b96cbf8 | |
Robert Lützner | facf38955c | |
MSTCL | cfdb890eae | |
Thomas J Faughnan Jr | 2f8d3a7958 | |
Frédéric Guillot | 59311deb57 | |
dependabot[bot] | d2541a173a | |
Frédéric Guillot | b618c11b80 | |
Frédéric Guillot | 8b4675807a | |
Frédéric Guillot | c0bca973d6 | |
krvpb024 | 5c97771e61 | |
dependabot[bot] | c9cbe8afd5 | |
knrdl | 1d90ce9dd2 | |
knrdl | ccb9eed573 | |
krvpb024 | 2221fd408d | |
Tân Î-sîn | ea58bac548 | |
krvpb024 | 0f85c0511a | |
krvpb024 | 27749a2877 | |
dependabot[bot] | 0991c27f9d | |
dependabot[bot] | 00eab03655 | |
dependabot[bot] | e55377b204 | |
dependabot[bot] | 4ddc4ec002 | |
krvpb024 | facf17db3f | |
dependabot[bot] | 8663c7d031 | |
krvpb024 | 6eac968083 | |
Frédéric Guillot | bd573957e0 | |
Frédéric Guillot | 5ce5c47499 | |
Frédéric Guillot | 9336891e67 | |
Frédéric Guillot | aa30c35e7e | |
krvpb024 | 39368ece9a | |
krvpb024 | 4f57309380 | |
krvpb024 | 57e7bd5bc9 | |
krvpb024 | bf54222be7 | |
Sheogorath | 552fb3e4cc | |
Frédéric Guillot | 7d9f174b3f | |
Frédéric Guillot | bf4d31eebe | |
Frédéric Guillot | f203326a29 | |
krvpb024 | 8367413e84 | |
krvpb024 | 9b6dbd422c | |
krvpb024 | 531e80f580 | |
krvpb024 | 890a34e1bd | |
krvpb024 | 7413e383a8 | |
krvpb024 | 7496479380 | |
krvpb024 | 6c78a1d635 | |
krvpb024 | 6413c9f9f7 | |
krvpb024 | 352aeb0490 | |
krvpb024 | 61f52d971a | |
krvpb024 | fa7508e28d | |
krvpb024 | c217a31444 | |
krvpb024 | 84576f2c29 | |
krvpb024 | da11416b39 | |
krvpb024 | 6a9a590c7f | |
krvpb024 | f23e6a3352 | |
krvpb024 | b568b1d41d | |
dependabot[bot] | 9980634e5d | |
Matt Stobo | 4a50ca9122 | |
dependabot[bot] | 3be0d14d44 | |
dependabot[bot] | ec9fd996b1 | |
MDeLuise | 1e704468a5 | |
Frédéric Guillot | e8147f26b9 | |
Andrew Gunnerson | 6648e0af38 | |
dependabot[bot] | fde84d55ba | |
Dave | 1159dd6982 | |
Frédéric Guillot | 50341759b6 | |
dzaikos | d68f2306c6 | |
Christoffer Strömblad | 578743de1f | |
Frédéric Guillot | 8553188ae4 | |
Frédéric Guillot | a3e2570df2 | |
Frédéric Guillot | 87c9ef6b48 | |
Frédéric Guillot | ce32d181d5 | |
dependabot[bot] | b8c6c64e9c | |
dependabot[bot] | c51f092bda | |
Frédéric Guillot | e2d33f680e | |
Ryan Stafford | 980c5c63df | |
Filipe de Luna | 1441dc7600 | |
dependabot[bot] | 6fc4e2f45e | |
dependabot[bot] | 8c00dbcf38 | |
dependabot[bot] | 803e160c70 | |
notsmarthuman | 4590da2fc3 | |
Dark Dragon | a1879ea37c | |
dependabot[bot] | 8fe289ca72 | |
Stephan Brauer | eb9ac861ea | |
Jan Tojnar | 074393d3bf | |
dependabot[bot] | 538e5305d3 | |
dependabot[bot] | 917852bbb0 | |
dependabot[bot] | c4e0dc3f5e | |
dependabot[bot] | 22ed3a3565 | |
dependabot[bot] | 80853d48f5 | |
Darwin | d90667777f | |
Frédéric Guillot | 7990edd345 | |
dependabot[bot] | 648804e5dc | |
dependabot[bot] | 187e75de4d | |
dependabot[bot] | e5df7ab3ad | |
Kristof Mattei | 0465f9b188 | |
Kristof Mattei | d53ad3b79a | |
Ole Bertram | 698bea4ec8 | |
Jesse Jaggars | 95039410b5 | |
Jesse Jaggars | e933fb11e9 | |
dependabot[bot] | 0666d98648 | |
dependabot[bot] | e314ae6df0 | |
Shizun Ge | bcb0978e9e | |
Shizun Ge | f3f892f448 | |
Frédéric Guillot | 1af1bc3460 | |
Frédéric Guillot | d0f99cee1a | |
dependabot[bot] | f8b40085cd | |
Frédéric Guillot | 5de0714256 | |
Shizun Ge | bfa83cbf99 | |
Shizun Ge | 27ec6dbd7d | |
Shizun Ge | a8daee60fb | |
Sam Crang | fab423cca0 | |
Shizun Ge | 70b69ecd19 | |
Thomas J Faughnan Jr | fe0ef8b579 | |
dependabot[bot] | 586a04f812 | |
dependabot[bot] | 293034bcde | |
dependabot[bot] | ac516a4824 | |
Shizun Ge | 65e2fddfb5 | |
dependabot[bot] | 2d167ae9f9 | |
Shizun Ge | 32779f596f | |
Shizun Ge | 273b96bfe0 | |
Shizun Ge | 4ffc073153 | |
dependabot[bot] | fc841beedd | |
dependabot[bot] | 9f4723f8eb | |
mrchi | b37bb43e09 | |
Thomas J Faughnan Jr | 7a03291442 | |
dependabot[bot] | 14f70351c0 | |
Frédéric Guillot | d195ce6340 | |
Frédéric Guillot | e9480ba1da | |
Frédéric Guillot | 1bd5d57884 | |
dependabot[bot] | 6544e413b8 | |
Frédéric Guillot | d7437f125b | |
Frédéric Guillot | f2849ca00f | |
Frédéric Guillot | aa3dc574a7 | |
Frédéric Guillot | ba65556eac | |
Nick Parker | 2bc5ad53c2 | |
Frédéric Guillot | bc317cfcd1 | |
dependabot[bot] | 00a64710c2 | |
Frédéric Guillot | ba614af82d | |
Frédéric Guillot | 2b8342fcd5 | |
Frédéric Guillot | a75256bed5 | |
Frédéric Guillot | 0cc369a76e | |
Florian Rüchel | 62ef8ed57a | |
dependabot[bot] | 62188b49f0 | |
Frédéric Guillot | 305d5ad7b6 | |
Frédéric Guillot | d8c82829c4 | |
Frédéric Guillot | e3eaaea15a | |
Frédéric Guillot | 500c60b807 | |
James Loh | ef53bf14ae | |
dependabot[bot] | 25f9ca2eeb | |
Nicolas Martinelli | d566dea265 | |
dependabot[bot] | c81b61462e | |
dependabot[bot] | 1fe362ecd0 | |
Nicholas Parker | 257e8c4761 | |
Tianfeng Wang | a1537f4b0d | |
Frédéric Guillot | eeaab72a9f | |
Frédéric Guillot | 14e25ab9fe | |
Ryan Stafford | 120aabfbce | |
Frédéric Guillot | 5e6c054345 | |
dependabot[bot] | ed35555d74 | |
dependabot[bot] | 619584b5f6 | |
Frédéric Guillot | 4cc99881d8 | |
Frédéric Guillot | 95ee1c423b | |
Frédéric Guillot | ff204d67b9 | |
Frédéric Guillot | 5ac3489ee5 | |
Frédéric Guillot | 9fd2dfa680 | |
Frédéric Guillot | 7650c81ad9 | |
Frédéric Guillot | c60b3f52a5 | |
Frédéric Guillot | 23d2cfe0f9 | |
Frédéric Guillot | 5dc44453ba | |
mcnesium | 6086899b28 | |
Frédéric Guillot | 2842017b59 | |
Frédéric Guillot | cc44d14722 | |
Frédéric Guillot | 54eb500315 | |
Frédéric Guillot | 0fe347c87a | |
jinmiaoluo | fd69012357 | |
dependabot[bot] | 9f62704c67 | |
Frédéric Guillot | 52cf236699 | |
Frédéric Guillot | e4285c2cba | |
Frédéric Guillot | 7b541af253 | |
Frédéric Guillot | 09e9b0361d | |
Frédéric Guillot | d0377d5d9d | |
dependabot[bot] | fe21f6a8c4 | |
dependabot[bot] | 6e85848bd0 | |
Frédéric Guillot | 2002d60fbe | |
Frédéric Guillot | 5774323f2e | |
Frédéric Guillot | 1350f84ea4 | |
Frédéric Guillot | 6dd090a848 | |
Frédéric Guillot | fccc25f7a3 | |
Frédéric Guillot | 67eb574fd4 | |
dependabot[bot] | a69b161725 | |
dependabot[bot] | 35fe8a23cb | |
Frédéric Guillot | a96702757e | |
Frédéric Guillot | f98fc1e03a | |
Frédéric Guillot | 39d752ca85 | |
dependabot[bot] | a7e08054da | |
Jany | e0e8a99abe | |
Frédéric Guillot | c0e954f19d | |
Adriano Di Luzio | 54cb8fa028 | |
Paul W. Rankin | ace2699e79 | |
dependabot[bot] | 59c003bdce | |
dependabot[bot] | 736d32c392 | |
dependabot[bot] | add2f8ac80 | |
dependabot[bot] | 22bbeef41a | |
dependabot[bot] | 192f48b7f2 | |
dependabot[bot] | dfcae03f25 | |
Frédéric Guillot | 545c68a0fd | |
Frédéric Guillot | b454d93c25 | |
Frédéric Guillot | a73d58aad5 | |
Frédéric Guillot | 2104eb85d7 | |
Frédéric Guillot | 9990afb722 | |
Frédéric Guillot | ca6af9684a | |
Frédéric Guillot | cb228e73ad | |
Andrey Voloshin | d33db40b39 | |
Frédéric Guillot | 3d84b07532 | |
Frédéric Guillot | 3b94217fb7 | |
Frédéric Guillot | 48f6885f44 | |
fuchsrot | 32d33104a4 | |
Frédéric Guillot | 939a91e99d | |
Frédéric Guillot | fbce915d84 | |
Frédéric Guillot | ab0c4ec0f5 | |
Frédéric Guillot | 36f013670e | |
Andrew Gunnerson | 344a237af8 | |
Frédéric Guillot | 5ce912beea | |
Magnus Åhall | 69738bce84 | |
dependabot[bot] | a0ae5a6868 | |
Frédéric Guillot | ff5d391701 | |
Cp Dong | fa1148915e | |
Dror Levin | bea9017b48 | |
Yury Paraschenko | 64c4c6b347 | |
Frédéric Guillot | 114f9f238d | |
Frédéric Guillot | 369c988576 | |
jgbresson | 691f56fde9 | |
dependabot[bot] | b2467fdd50 | |
Frédéric Guillot | 5e520ca5bf | |
Frédéric Guillot | e5d9f2f5a0 | |
Frédéric Guillot | 9f465fd70d | |
Frédéric Guillot | 28df0b119e | |
Frédéric Guillot | 13d9d86acd | |
Romain de Laage | fb8737e330 | |
Frédéric Guillot | 168a870c02 | |
Frédéric Guillot | c234903255 | |
Frédéric Guillot | c980dfe434 | |
njzy | 79c91d71c8 | |
Kierán Meinhardt | 3060946cc1 | |
Frédéric Guillot | 859b4466ab | |
dependabot[bot] | 124b770ff6 | |
dependabot[bot] | 6b6e60ee0d | |
dependabot[bot] | 10aa20e9cd | |
Frédéric Guillot | 97c68ce55a | |
Jean Khawand | 061f12fbb0 | |
Jean Khawand | bf4823bdbd | |
Jean Khawand | da0198cc0d | |
dependabot[bot] | 31538c57a4 | |
Frédéric Guillot | 955650d1e3 | |
Frédéric Guillot | e7ccf0aa1e | |
dependabot[bot] | e2fb77bd85 | |
Jean Khawand | de8ceb21ea | |
Corey McCaffrey | 3bac768cda | |
Frédéric Guillot | 3aad650622 | |
dependabot[bot] | d4fbaaed0c | |
Frédéric Guillot | 4a4c309da0 | |
Frédéric Guillot | 5e76c797c2 | |
David Izquierdo | 4fdef7b837 | |
Frédéric Guillot | 7988241e11 | |
Frédéric Guillot | 309e6d1084 | |
dependabot[bot] | 92bb040640 | |
Igor Rzegocki | 9b42d0e25e | |
Frédéric Guillot | f286c3c1c9 | |
Tuukka Ojala | e16870a638 | |
Tuukka Ojala | f0eb6b2688 | |
Tuukka Ojala | 29a06511a9 | |
Jean Khawand | bfb4fc1c36 | |
dependabot[bot] | 06c37a132f | |
mrtnvgr | 70b3061946 | |
xl | 356d32c6fe | |
mrtnvgr | 6046a74a64 | |
dependabot[bot] | 56fbea4bd3 | |
Wayne Tan | ee0dcdf753 | |
Frédéric Guillot | 5550d662a2 | |
Frédéric Guillot | 3dc8e5ebaf | |
Frédéric Guillot | c85b19098d | |
kramanathan01 | c3250257b1 | |
privatmamtora | fffa74f782 | |
kramanathan01 | fa3de272e8 | |
Frédéric Guillot | b13c7e328a | |
Frédéric Guillot | 30d4b8986a | |
Frédéric Guillot | aadbd5adf3 | |
Frédéric Guillot | b552c293ca | |
Frédéric Guillot | a2f15b3c36 | |
movd | 736fb7320e | |
Gabriel Augendre | 765b4c6424 | |
Frédéric Guillot | df472254d3 | |
Frédéric Guillot | 98167487aa | |
Frédéric Guillot | 257ef7e573 | |
Frédéric Guillot | 30288fec8d | |
Frédéric Guillot | e234b86af6 | |
dependabot[bot] | d00803617e | |
fred | af74e39fa7 | |
fred | 8646d61182 | |
fred | 28775f5e10 | |
dependabot[bot] | 095bec072c | |
dependabot[bot] | bd0f21e139 | |
dependabot[bot] | 69414dcd7c | |
Kristof Mattei | 28ee9cad19 | |
Naïm Favier | 7d1609bd93 | |
Ryan Stafford | 1aeb1b20da | |
Ztec | 228bb62df4 | |
Ryan Cao | c4e2eaa609 | |
Romain de Laage | 118e18190d | |
Jonatas Baldin | 31c4172540 | |
dependabot[bot] | 93b43d37df | |
Frédéric Guillot | 3987a2ce8a | |
Frédéric Guillot | fe039b3c55 | |
dependabot[bot] | 7537932154 | |
dependabot[bot] | 902f6cb9c0 | |
Frédéric Guillot | 790ce5be6d | |
dependabot[bot] | bcfc7a883c | |
Pontus Jensen Karlsson | 9fdbd180df | |
Frédéric Guillot | 4c0c658152 | |
dependabot[bot] | 88062ab9f9 | |
Adriano Di Luzio | 85856baf13 | |
dependabot[bot] | 2d33b7df6e | |
Davide Masserut | 5d8a8878d5 | |
dependabot[bot] | 8d2dab44d8 | |
dependabot[bot] | d435e67a36 | |
Romain de Laage | 33c4b5188c | |
dependabot[bot] | 8161085714 | |
dependabot[bot] | 6493239484 | |
dependabot[bot] | a143681af3 | |
Emiel Wiedijk | 5a88e0465e | |
dependabot[bot] | 30bb901d7c | |
dependabot[bot] | 40418fcf6f | |
dependabot[bot] | ad85e5be80 | |
Frédéric Guillot | aa9b18a8d6 | |
Jake Walker | 8b6dd3e599 | |
Jake Walker | 49d2596fc6 | |
rook1e | 9a826bbe6f | |
rook1e | acc9186a59 | |
dzaikos | 7d252ea45b | |
Frédéric Guillot | 140a40acaf | |
toastal | 56efba66f5 | |
Frédéric Guillot | 7e612cddd3 | |
Davide Masserut | 034e46700c | |
Daniel Jakots | ac8f64d7a1 | |
Daniel Jakots | b536e05fee | |
dependabot[bot] | 6eed037186 | |
Frédéric Guillot | 5912400dee | |
Frédéric Guillot | ab209df78f | |
dependabot[bot] | 11a352dcfd | |
Frédéric Guillot | 9ae6922bdc | |
Frédéric Guillot | ea8c3c801a | |
Frédéric Guillot | eb9508502c | |
Frédéric Guillot | b46b5dfb2a | |
Frédéric Guillot | 877dbed5e8 | |
fructurj | 79ff381c4c | |
dependabot[bot] | f6a672738a | |
dependabot[bot] | e4964d6933 | |
Davide Masserut | 755c9af47d | |
Frédéric Guillot | 02e4b8eadc | |
Frédéric Guillot | aaa1625724 | |
Frédéric Guillot | bb5f3ec6a8 | |
Sigsign | 8804eb9a78 | |
Romain de Laage | 2c2700a31d | |
privatmamtora | 8f9ccc6540 | |
dependabot[bot] | ff8d68c151 | |
the7thNightmare | 1fb0bc29db | |
Ananta Krsna dasa | a1593b8942 | |
Ananta Krsna dasa | 20c4cb770e | |
Ananta Krsna dasa | db7a4ae7e9 | |
the7thNightmare | aabb766fad | |
the7thNightmare | 8dce3099d9 | |
dependabot[bot] | fb2b43176f | |
dependabot[bot] | 2f6034c63c | |
dependabot[bot] | 67190fc988 | |
dependabot[bot] | e4c0495646 | |
dependabot[bot] | a7508b2746 | |
Wojtek | 34408b50a7 | |
Marie Ramlow | 48acd1feca | |
Ryan Cao | 8d51fd8ff5 | |
Martin Vietz | a44ba4abcb | |
dependabot[bot] | b338c9b3c2 | |
xdavidwu | 08f7835f5d | |
dependabot[bot] | d38fc80bad | |
Frédéric Guillot | b2fd84e0d3 | |
Sigsign | e64f488654 | |
Sigsign | 8017ed2cf6 | |
Davide Masserut | 65febebd40 | |
Frédéric Guillot | 2e047dff98 | |
Frédéric Guillot | 6612e42668 | |
dependabot[bot] | 2956bbad8d | |
dependabot[bot] | 3285a00ebc | |
dependabot[bot] | c0c8e47344 | |
dependabot[bot] | 3fc02df70f | |
Tadeusz Magura-Witkowski | c071201e37 | |
Davide Masserut | 690d66ce0b | |
Davide Masserut | ef312ef770 | |
Davide Masserut | c0bed53b42 | |
Davide Masserut | c0ee3ed375 | |
Davide Masserut | ce35b46fee | |
Frédéric Guillot | e12c263fc9 | |
dependabot[bot] | 281c9be6c8 | |
dependabot[bot] | b92debf9c9 | |
nyanpasu64 | b6c368c39c | |
dependabot[bot] | de92e3e472 | |
Harry Cheng | d9777f1439 | |
mutantmonkey | b4643fd27f | |
Frédéric Guillot | d9cf3f9c38 | |
Frédéric Guillot | dfd6b769b9 | |
dependabot[bot] | 68780de6fc | |
Frédéric Guillot | 93715b542c | |
Frédéric Guillot | de1a06e3e8 | |
Frédéric Guillot | bfebf946c2 | |
Frédéric Guillot | 6094130f61 | |
Frédéric Guillot | d1bd0073cc | |
Juan Pedro Bretti Mandarano | 789e30fdff | |
Juan Pedro Bretti Mandarano | 04507a8a34 | |
Frédéric Guillot | 1ded3f8bc7 | |
Frédéric Guillot | 3d64162f06 | |
George Angelopoulos | 79357a527f | |
George Angelopoulos | 1e16e19d11 | |
Romain de Laage | efa8bfcf0e | |
dependabot[bot] | 1351761f81 | |
dependabot[bot] | 962a0460cc | |
jebbs | 10207967c4 | |
Frédéric Guillot | 242eeaf07e | |
Romain de Laage | 550e7d0415 | |
Romain de Laage | 3f14d08095 | |
Frédéric Guillot | 206be5ba15 | |
Romain de Laage | 83e1f154b5 | |
Romain de Laage | ec47106c26 | |
Dave Marquard | 74b69a4c7c | |
George Angelopoulos | 84d5a9a354 | |
Romain de Laage | eb86773039 | |
Michael van Tricht | 44ca5b8591 |
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "Miniflux",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "app",
|
||||
"workspaceFolder": "/workspace",
|
||||
"remoteUser": "vscode",
|
||||
"forwardPorts": [
|
||||
8080
|
||||
],
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"go.toolsManagement.checkForUpdates": "local",
|
||||
"go.useLanguageServer": true,
|
||||
"go.gopath": "/go"
|
||||
},
|
||||
"extensions": [
|
||||
"ms-azuretools.vscode-docker",
|
||||
"golang.go",
|
||||
"rangav.vscode-thunder-client",
|
||||
"GitHub.codespaces",
|
||||
"GitHub.copilot",
|
||||
"GitHub.copilot-chat"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
version: '3.8'
|
||||
services:
|
||||
app:
|
||||
image: mcr.microsoft.com/devcontainers/go:1.22
|
||||
volumes:
|
||||
- ..:/workspace:cached
|
||||
command: sleep infinity
|
||||
network_mode: service:db
|
||||
environment:
|
||||
- CREATE_ADMIN=1
|
||||
- ADMIN_USERNAME=admin
|
||||
- ADMIN_PASSWORD=test123
|
||||
db:
|
||||
image: postgres:15
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
hostname: postgres
|
||||
environment:
|
||||
POSTGRES_DB: miniflux2
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
ports:
|
||||
- 5432:5432
|
||||
apprise:
|
||||
image: caronc/apprise:1.0
|
||||
restart: unless-stopped
|
||||
hostname: apprise
|
||||
volumes:
|
||||
postgres-data: null
|
|
@ -2,7 +2,7 @@
|
|||
name: Bug report
|
||||
about: Create a bug report
|
||||
title: ''
|
||||
labels: bug
|
||||
labels: bug, triage needed
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name: Feed Problems
|
||||
about: Problems with a feed or a website
|
||||
title: ''
|
||||
labels: feed problems
|
||||
labels: feed problems, triage needed
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
name: Improvement
|
||||
about: Do you have an idea to improve an existing feature?
|
||||
title: ''
|
||||
labels: improvements
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
name: Installation Issue
|
||||
about: Do you need help to install Miniflux?
|
||||
title: ''
|
||||
labels: installation issue
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
name: Question / Discussion
|
||||
about: Open discussions
|
||||
title: ''
|
||||
labels: question / discussion
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
paths-ignore:
|
||||
- ./http/client/testdata
|
|
@ -3,7 +3,7 @@ updates:
|
|||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
interval: "daily"
|
||||
reviewers:
|
||||
- "fguillot"
|
||||
assignees:
|
||||
|
@ -27,6 +27,24 @@ updates:
|
|||
assignees:
|
||||
- "fguillot"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "packaging/debian"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
reviewers:
|
||||
- "fguillot"
|
||||
assignees:
|
||||
- "fguillot"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "packaging/rpm"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
reviewers:
|
||||
- "fguillot"
|
||||
assignees:
|
||||
- "fguillot"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
Do you follow the guidelines?
|
||||
|
||||
- [ ] I have tested my changes
|
||||
- [ ] There is no breaking changes
|
||||
- [ ] I really tested my changes and there is no regression
|
||||
- [ ] Ideally, my commit messages use the same convention as the Go project: https://go.dev/doc/contribute#commit_messages
|
||||
- [ ] I read this document: https://miniflux.app/faq.html#pull-request
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
name: Build Binaries
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Golang
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22.x"
|
||||
check-latest: true
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Compile binaries
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
run: make build
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: binaries
|
||||
path: miniflux-*
|
||||
if-no-files-found: error
|
||||
retention-days: 5
|
|
@ -27,16 +27,17 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22.x"
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: ./.github/codeql/config.yml
|
||||
uses: github/codeql-action/init@v3
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
name: Debian Packages
|
||||
permissions: read-all
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
jobs:
|
||||
test-packages:
|
||||
if: github.event.pull_request
|
||||
name: Test Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
with:
|
||||
install: true
|
||||
- name: Available Docker Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
- name: Build Debian Packages
|
||||
run: make debian-packages
|
||||
- name: List generated files
|
||||
run: ls -l *.deb
|
||||
build-packages-manually:
|
||||
if: github.event_name != 'pull_request' && github.event_name != 'push'
|
||||
name: Build Packages Manually
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
with:
|
||||
install: true
|
||||
- name: Available Docker Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
- name: Build Debian Packages
|
||||
run: make debian-packages
|
||||
- name: Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages
|
||||
path: "*.deb"
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
publish-packages:
|
||||
if: github.event_name == 'push'
|
||||
name: Publish Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
with:
|
||||
install: true
|
||||
- name: Available Docker Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
- name: Build Debian Packages
|
||||
run: make debian-packages
|
||||
- name: List generated files
|
||||
run: ls -l *.deb
|
||||
- name: Upload packages to repository
|
||||
env:
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
run: for f in *.deb; do curl -F package=@$f https://$FURY_TOKEN@push.fury.io/miniflux/; done
|
|
@ -1,81 +1,95 @@
|
|||
name: Docker
|
||||
permissions: read-all
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 1 * * *'
|
||||
push:
|
||||
tags:
|
||||
- '*.*.*'
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
jobs:
|
||||
docker-images:
|
||||
name: Docker Images
|
||||
permissions:
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate Alpine Docker tag
|
||||
id: docker_alpine_tag
|
||||
run: |
|
||||
DOCKER_IMAGE=${{ github.repository_owner }}/miniflux
|
||||
DOCKER_VERSION=dev
|
||||
if [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
DOCKER_VERSION=nightly
|
||||
TAGS="${DOCKER_IMAGE}:${DOCKER_VERSION},ghcr.io/${DOCKER_IMAGE}:${DOCKER_VERSION}"
|
||||
elif [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
DOCKER_VERSION=${GITHUB_REF#refs/tags/}
|
||||
TAGS="${DOCKER_IMAGE}:${DOCKER_VERSION},ghcr.io/${DOCKER_IMAGE}:${DOCKER_VERSION},${DOCKER_IMAGE}:latest,ghcr.io/${DOCKER_IMAGE}:latest"
|
||||
fi
|
||||
echo ::set-output name=tags::${TAGS}
|
||||
- name: Generate Alpine Docker tags
|
||||
id: docker_alpine_tags
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
docker.io/${{ github.repository_owner }}/miniflux
|
||||
ghcr.io/${{ github.repository_owner }}/miniflux
|
||||
quay.io/${{ github.repository_owner }}/miniflux
|
||||
tags: |
|
||||
type=ref,event=pr
|
||||
type=schedule,pattern=nightly
|
||||
type=semver,pattern={{raw}}
|
||||
|
||||
- name: Generate Distroless Docker tag
|
||||
id: docker_distroless_tag
|
||||
run: |
|
||||
DOCKER_IMAGE=${{ github.repository_owner }}/miniflux
|
||||
DOCKER_VERSION=dev-distroless
|
||||
if [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
DOCKER_VERSION=nightly-distroless
|
||||
TAGS="${DOCKER_IMAGE}:${DOCKER_VERSION},ghcr.io/${DOCKER_IMAGE}:${DOCKER_VERSION}"
|
||||
elif [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
DOCKER_VERSION=${GITHUB_REF#refs/tags/}-distroless
|
||||
TAGS="${DOCKER_IMAGE}:${DOCKER_VERSION},ghcr.io/${DOCKER_IMAGE}:${DOCKER_VERSION},${DOCKER_IMAGE}:latest-distroless,ghcr.io/${DOCKER_IMAGE}:latest-distroless"
|
||||
fi
|
||||
echo ::set-output name=tags::${TAGS}
|
||||
- name: Generate Distroless Docker tags
|
||||
id: docker_distroless_tags
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
docker.io/${{ github.repository_owner }}/miniflux
|
||||
ghcr.io/${{ github.repository_owner }}/miniflux
|
||||
quay.io/${{ github.repository_owner }}/miniflux
|
||||
tags: |
|
||||
type=ref,event=pr
|
||||
type=schedule,pattern=nightly
|
||||
type=semver,pattern={{raw}}
|
||||
flavor: |
|
||||
suffix=-distroless,onlatest=true
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.CR_PAT }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Quay Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: quay.io
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_TOKEN }}
|
||||
|
||||
- name: Build and Push Alpine images
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./packaging/docker/alpine/Dockerfile
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_alpine_tag.outputs.tags }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.docker_alpine_tags.outputs.tags }}
|
||||
|
||||
- name: Build and Push Distroless images
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./packaging/docker/distroless/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_distroless_tag.outputs.tags }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.docker_distroless_tags.outputs.tags }}
|
||||
|
|
|
@ -5,27 +5,35 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
jshint:
|
||||
name: Javascript Linter
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install jshint
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install linters
|
||||
run: |
|
||||
sudo npm install -g jshint@2.13.3
|
||||
sudo npm install -g jshint@2.13.6 eslint@8.57.0
|
||||
- name: Run jshint
|
||||
run: jshint ui/static/js/*.js
|
||||
run: jshint internal/ui/static/js/*.js
|
||||
- name: Run ESLint
|
||||
run: eslint internal/ui/static/js/*.js
|
||||
|
||||
golangci:
|
||||
name: Golang Linter
|
||||
name: Golang Linters
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.19
|
||||
- uses: golangci/golangci-lint-action@v3
|
||||
go-version: "1.22.x"
|
||||
- run: "go vet ./..."
|
||||
- uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
args: --skip-dirs tests --disable errcheck --enable sqlclosecheck --enable misspell --enable gofmt --enable goimports --enable whitespace
|
||||
args: --timeout 10m --skip-dirs tests --disable errcheck --enable sqlclosecheck --enable misspell --enable gofmt --enable goimports --enable whitespace --enable gocritic
|
||||
- uses: dominikh/staticcheck-action@v1.3.1
|
||||
with:
|
||||
version: "2023.1.7"
|
||||
install-go: false
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
name: Debian and RPM Package Builders
|
||||
permissions: read-all
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*.*.*'
|
||||
jobs:
|
||||
debian-package-builder:
|
||||
name: Build Debian Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
id: buildx
|
||||
with:
|
||||
install: true
|
||||
- name: Available Docker Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
- name: Build Debian Packages
|
||||
run: make debian-packages
|
||||
- name: List generated files
|
||||
run: ls -l *.deb
|
||||
- name: Upload packages to repository
|
||||
env:
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
run: for f in *.deb; do curl -F package=@$f https://$FURY_TOKEN@push.fury.io/miniflux/; done
|
||||
rpm-package-builder:
|
||||
name: Build RPM Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build RPM Package
|
||||
run: make rpm
|
||||
- name: List generated files
|
||||
run: ls -l *.rpm
|
||||
- name: Upload package to repository
|
||||
env:
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
run: for f in *.rpm; do curl -F package=@$f https://$FURY_TOKEN@push.fury.io/miniflux/; done
|
|
@ -0,0 +1,55 @@
|
|||
name: RPM Packages
|
||||
permissions: read-all
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
jobs:
|
||||
test-package:
|
||||
if: github.event.pull_request
|
||||
name: Test Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build RPM Package
|
||||
run: make rpm
|
||||
- name: List generated files
|
||||
run: ls -l *.rpm
|
||||
build-package-manually:
|
||||
if: github.event_name != 'pull_request' && github.event_name != 'push'
|
||||
name: Build Packages Manually
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build RPM Package
|
||||
run: make rpm
|
||||
- name: Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages
|
||||
path: "*.rpm"
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
publish-package:
|
||||
if: github.event_name == 'push'
|
||||
name: Publish Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build RPM Package
|
||||
run: make rpm
|
||||
- name: List generated files
|
||||
run: ls -l *.rpm
|
||||
- name: Upload package to repository
|
||||
env:
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
run: for f in *.rpm; do curl -F package=@$f https://$FURY_TOKEN@push.fury.io/miniflux/; done
|
|
@ -1,10 +1,11 @@
|
|||
name: CI Workflow
|
||||
name: Tests
|
||||
permissions: read-all
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
|
@ -14,14 +15,14 @@ jobs:
|
|||
max-parallel: 4
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
go-version: [1.18, 1.19]
|
||||
go-version: ["1.22.x"]
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Run unit tests
|
||||
run: make test
|
||||
|
||||
|
@ -40,11 +41,11 @@ jobs:
|
|||
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: "1.22.x"
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Postgres client
|
||||
run: sudo apt update && sudo apt install -y postgresql-client
|
||||
- name: Run integration tests
|
|
@ -1,5 +1,6 @@
|
|||
miniflux-*
|
||||
miniflux
|
||||
./miniflux
|
||||
*.rpm
|
||||
*.deb
|
||||
.idea
|
||||
.idea
|
||||
.vscode
|
601
ChangeLog
601
ChangeLog
|
@ -1,3 +1,604 @@
|
|||
Version 2.1.3 (April 27, 2024)
|
||||
------------------------------
|
||||
|
||||
* `api`: `rand.Intn(math.MaxInt64)` causes tests to fail on 32-bit architectures (use `rand.Int()` instead)
|
||||
* `ci`: use `docker/metadata-action` instead of deprecated shell-scripts
|
||||
* `database`: remove `entries_feed_url_idx` index because entry URLs can exceeds btree index size limit
|
||||
* `finder`: find feeds from YouTube playlist
|
||||
* `http/response`: add brotli compression support
|
||||
* `integration/matrix`: fix function name in comment
|
||||
* `packaging`: specify container registry explicitly (e.g., Podman does not use `docker.io` by default)
|
||||
* `packaging`: use `make miniflux` instead of duplicating `go build` arguments (this leverages Go's PIE build mode)
|
||||
* `reader/fetcher`: add brotli content encoding support
|
||||
* `reader/processor`: minimize feed entries HTML content
|
||||
* `reader/rewrite`: add a rule for `oglaf.com`
|
||||
* `storage`: change `GetReadTime()` function to use `entries_feed_id_hash_key` index
|
||||
* `ui`: add seek and speed controls to media player
|
||||
* `ui`: add tag entries page
|
||||
* `ui`: fix JavaScript error when clicking on unread counter
|
||||
* `ui`: use `FORCE_REFRESH_INTERVAL` config for category refresh
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.19` to `2.20.20`
|
||||
* Bump `golang.org/x/net` from `0.22.0` to `0.24.0`
|
||||
* Bump `golang.org/x/term` from `0.18.0` to `0.19.0`
|
||||
* Bump `golang.org/x/oauth2` from `0.18.0` to `0.19.0`
|
||||
* Bump `github.com/yuin/goldmark` from `1.7.0` to `1.7.1`
|
||||
|
||||
Version 2.1.2 (March 30, 2024)
|
||||
------------------------------
|
||||
|
||||
* `api`: rewrite API integration tests without build tags
|
||||
* `ci`: add basic ESLinter checks
|
||||
* `ci`: enable go-critic linter and fix various issues detected
|
||||
* `ci`: fix JavaScript linter path in GitHub Actions
|
||||
* `cli`: avoid misleading error message when creating an admin user automatically
|
||||
* `config`: add `FILTER_ENTRY_MAX_AGE_DAYS` option
|
||||
* `config`: bump the number of simultaneous workers
|
||||
* `config`: rename `PROXY_*` options to `MEDIA_PROXY_*`
|
||||
* `config`: use `crypto.GenerateRandomBytes` instead of doing it by hand
|
||||
* `http/request`: refactor conditions to be more idiomatic
|
||||
* `http/response`: remove legacy `X-XSS-Protection` header
|
||||
* `integration/rssbrige`: fix rssbrige import
|
||||
* `integration/shaarli`: factorize the header+payload concatenation as data
|
||||
* `integration/shaarli`: no need to base64-encode then remove the padding when we can simply encode without padding
|
||||
* `integration/shaarli`: the JWT token was declared as using HS256 as algorithm, but was using HS512
|
||||
* `integration/webhook`: add category title to request body
|
||||
* `locale`: update Turkish translations
|
||||
* `man page`: sort config options in alphabetical order
|
||||
* `mediaproxy`: reduce the internal indentation of `ProxifiedUrl` by inverting some conditions
|
||||
* `mediaproxy`: simplify and refactor the package
|
||||
* `model`: replace` Optional{Int,Int64,Float64}` with a generic function `OptionalNumber()`
|
||||
* `model`: use struct embedding for `FeedCreationRequestFromSubscriptionDiscovery` to reduce code duplication
|
||||
* `reader/atom`: avoid debug message when the date is empty
|
||||
* `reader/atom`: change `if !a { a = } if !a {a = }` constructs into `if !a { a = ; if !a {a = }}` to reduce the number of comparisons and improve readability
|
||||
* `reader/atom`: Move the population of the feed's entries into a new function, to make BuildFeed easier to understand/separate concerns/implementation details
|
||||
* `reader/atom`: refactor Atom parser to use an adapter
|
||||
* `reader/atom`: use `sort+compact` instead of `compact+sort` to remove duplicates
|
||||
* `reader/atom`: when detecting the format, detect its version as well
|
||||
* `reader/encoding`: inline a one-liner function
|
||||
* `reader/handler`: fix force refresh feature
|
||||
* `reader/json`: refactor JSON Feed parser to use an adapter
|
||||
* `reader/media`: remove a superfluous error-check: `strconv.ParseInt` returns `0` when passed an empty string
|
||||
* `reader/media`: simplify switch-case by moving a common condition above it
|
||||
* `reader/processor`: compile block/keep regex only once per feed
|
||||
* `reader/rdf`: refactor RDF parser to use an adapter
|
||||
* `reader/rewrite`: inline some one-line functions
|
||||
* `reader/rewrite`: simplify `removeClickbait`
|
||||
* `reader/rewrite`: transform a free-standing function into a method
|
||||
* `reader/rewrite`: use a proper constant instead of a magic number in `applyFuncOnTextContent`
|
||||
* `reader/rss`: add support for `<media:category>` element
|
||||
* `reader/rss`: don't add empty tags to RSS items
|
||||
* `reader/rss`: refactor RSS parser to use a default namespace to avoid some limitations of the Go XML parser
|
||||
* `reader/rss`: refactor RSS Parser to use an adapter
|
||||
* `reader/rss`: remove some duplicated code in RSS parser
|
||||
* `reader`: ensure that enclosure URLs are always absolute
|
||||
* `reader`: move iTunes and GooglePlay XML definitions to their own packages
|
||||
* `reader`: parse podcast categories
|
||||
* `reader`: remove trailing space in `SiteURL` and `FeedURL`
|
||||
* `storage`: do not store empty tags
|
||||
* `storage`: simplify `removeDuplicates()` to use a `sort`+`compact` construct instead of doing it by hand with a hashmap
|
||||
* `storage`: Use plain strings concatenation instead of building an array and then joining it
|
||||
* `timezone`: make sure the tests pass when the timezone database is not installed on the host
|
||||
* `ui/css`: align `min-width` with the other `min-width` values
|
||||
* `ui/css`: fix regression: "Add to Home Screen" button is unreadable
|
||||
* `ui/js`: don't use lambdas to return a function, use directly the function instead
|
||||
* `ui/js`: enable trusted-types
|
||||
* `ui/js`: fix download button loading label
|
||||
* `ui/js`: fix JavaScript error on the login page when the user not authenticated
|
||||
* `ui/js`: inline one-line functions
|
||||
* `ui/js`: inline some `querySelectorAll` calls
|
||||
* `ui/js`: reduce the scope of some variables
|
||||
* `ui/js`: remove a hack for "Chrome 67 and earlier" since it was released in 2018
|
||||
* `ui/js`: replace `DomHelper.findParent` with `.closest`
|
||||
* `ui/js`: replace `let` with `const`
|
||||
* `ui/js`: simplify `DomHelper.getVisibleElements` by using a `filter` instead of a loop with an index
|
||||
* `ui/js`: use a `Set` instead of an array in a `KeyboardHandler`'s member
|
||||
* `ui/js`: use some ternaries where it makes sense
|
||||
* `ui/static`: make use of `HashFromBytes` everywhere
|
||||
* `ui/static`: set minifier ECMAScript version
|
||||
* `ui`: add keyboard shortcuts for scrolling to top/bottom of the item list
|
||||
* `ui`: add media player control playback speed
|
||||
* `ui`: remove unused variables and improve JSON decoding in `saveEnclosureProgression()`
|
||||
* `validator`: display an error message on edit feed page when the feed URL is not unique
|
||||
* Bump `github.com/coreos/go-oidc/v3` from `3.9.0` to `3.10.0`
|
||||
* Bump `github.com/go-webauthn/webauthn` from `0.10.1` to `0.10.2`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.18` to `2.20.19`
|
||||
* Bump `google.golang.org/protobuf` from `1.32.0` to `1.33.0`
|
||||
|
||||
Version 2.1.1 (March 10, 2024)
|
||||
-----------------------------
|
||||
|
||||
* Move search form to a dedicated page
|
||||
* Add Readeck integration
|
||||
* Add feed option to disable HTTP/2 to avoid fingerprinting
|
||||
* Add `Enter` key as a hotkey to open selected item
|
||||
* Proxify `video` element `poster` attribute
|
||||
* Add a couple of new possible locations for feeds
|
||||
* Hugo likes to generate `index.xml`
|
||||
* `feed.atom` and `feed.rss` are used by enterprise-scale/old-school gigantic CMS
|
||||
* Fix categories import from Thunderbird's OPML
|
||||
* Fix logo misalignment when using languages that are more verbose than English
|
||||
* Google Reader: Do not return a 500 error when no items is returned
|
||||
* Handle RDF feeds with duplicated `<title>` elements
|
||||
* Sort integrations alphabetically
|
||||
* Add more URL validation in media proxy
|
||||
* Add unit test to ensure each translation has the correct number of plurals
|
||||
* Add missing plurals for some languages
|
||||
* Makefile: quiet `git describe` and `rev-parse` stderr: When building from a tarball instead of a cloned git repo, there would be two `fatal: not a git repository` errors emitted even though the build succeeds. This is because of how `VERSION` and `COMMIT` are set in the Makefile. This PR suppresses the stderr for these variable assignments.
|
||||
* Makefile: do not force `CGO_ENABLED=0` for `miniflux` target
|
||||
* Add GitHub Action pipeline to build packages on-demand
|
||||
* Remove Golint (deprecated), use `staticcheck` and `golangci-lint` instead
|
||||
* Build amd64/arm64 Debian packages with CGO disabled
|
||||
* Update `go.mod` and add `.exe` suffix to Windows binary
|
||||
* Add a couple of fuzzers
|
||||
* Fix CodeQL workflow
|
||||
* Code and performance improvements:
|
||||
* Use an `io.ReadSeeker` instead of an `io.Reader` to parse feeds
|
||||
* Speed up the sanitizer:
|
||||
- Allow Youtube URLs to start with `www`
|
||||
- Use `strings.Builder` instead of a `bytes.Buffer`
|
||||
- Use a `strings.NewReader` instead of a `bytes.NewBufferString`
|
||||
- Sprinkles a couple of `continue` to make the code-flow more obvious
|
||||
- Inline calls to `inList`, and put their parameters in the right order
|
||||
- Simplify `isPixelTracker`
|
||||
- Simplify `isValidIframeSource`, by extracting the hostname and comparing it directly, instead of using the full url and checking if it starts with multiple variations of the same one (`//`, `http:`, `https://` multiplied by `/www.`)
|
||||
- Add a benchmark
|
||||
- Instead of having to allocate a ~100 keys map containing possibly dynamic values (at least to the go compiler), allocate it once in a global variable. This significantly speeds things up, by reducing the garbage
|
||||
- Use constant time access for maps instead of iterating on them
|
||||
- Build a ~large whitelist map inline instead of constructing it item by item (and remove a duplicate key/value pair)
|
||||
- Use `slices` instead of hand-rolled loops
|
||||
collector/allocator involvements.
|
||||
* Reuse a `Reader` instead of copying to a buffer when parsing an Atom feed
|
||||
* Preallocate memory when exporting to OPML: This should marginally increase performance when exporting a large amount of feeds to OPML
|
||||
* Delay call of `view.New` after logging the user in: There is no need to do extra work like creating a session and its associated view until the user has been properly identified and as many possibly-failing sql request have been successfully run
|
||||
* Use constant-time comparison for anti-csrf tokens: This is probably completely overkill, but since anti-csrf tokens are secrets, they should be compared against untrusted inputs in constant time
|
||||
* Simplify and optimize `genericProxyRewriter`
|
||||
- Reduce the amount of nested loops: it's preferable to search the whole page once and filter on it (even with filters that should always be false), than searching it again for every element we're looking for.
|
||||
- Factorize the proxying conditions into a `shouldProxy` function to reduce the copy-pasta.
|
||||
* Speed up `removeUnlikelyCandidates`: `.Not` returns a brand new `Selection`, copied element by element
|
||||
* Improve `EstimateReadingTime`'s speed by a factor 7
|
||||
- Refactorise the tests and add some
|
||||
- Use 250 signs instead of the whole text
|
||||
- Only check for Korean, Chinese and Japanese script
|
||||
- Add a benchmark
|
||||
- Use a more idiomatic control flow
|
||||
* Don't compute reading-time when unused: If the user doesn't display reading times, there is no need to compute them. This should speed things up a bit, since `whatlanggo.Detect` is abysmally slow.
|
||||
* Simplify `username` generation for the integration tests: No need to generate random numbers 10 times, generate a single big-enough one. A single int64 should be more than enough
|
||||
* Add missing regex anchor detected by CodeQL
|
||||
* Don't mix up slices capacity and length
|
||||
* Use prepared statements for intervals, `ArchiveEntries` and `updateEnclosures`
|
||||
* Use modern for-loops introduced with Go 1.22
|
||||
* Remove a superfluous condition: No need to check if the length of `line` is positive since we're checking afterwards that it contains the `=` sign
|
||||
* Close resources as soon as possible, instead of using `defer()` in a loop
|
||||
* Remove superfluous escaping in a regex
|
||||
* Use `strings.ReplaceAll` instead of `strings.Replace(…, -1)`
|
||||
* Use `strings.EqualFold` instead of `strings.ToLower(…) ==`
|
||||
* Use `.WriteString(` instead of `.Write([]byte(…`
|
||||
* Use `%q` instead of `"%s"`
|
||||
* Make `internal/worker/worker.go` read-only
|
||||
* Use a switch-case construct in `internal/locale/plural.go` instead of an avalanche of `if`
|
||||
* Template functions: simplify `formatFileSize` and `duration` implementation
|
||||
* Inline some templating functions
|
||||
* Make use of `printer.Print` when possible
|
||||
* Add a `printer.Print` to `internal/locale/printer.go`: No need to use variadic functions with string format interpolation to generate static strings
|
||||
* Minor code simplification in `internal/ui/view/view.go`: No need to create the map item by item when we can create it in one go
|
||||
* Build the map inline in `CountAllFeeds()`: No need to build an empty map to then add more fields in it one by one
|
||||
* Miscellaneous improvements to `internal/reader/subscription/finder.go`:
|
||||
- Surface `localizedError` in `FindSubscriptionsFromWellKnownURLs` via `slog`
|
||||
- Use an inline declaration for new subscriptions, like done elsewhere in the
|
||||
file, if only for consistency's sake
|
||||
- Preallocate the `subscriptions` slice when using an RSS-bridge,
|
||||
* Use an update-where for `MarkCategoryAsRead` instead of a subquery
|
||||
* Simplify `CleanOldUserSessions`' query: No need for a subquery, filtering on `created_at` directly is enough
|
||||
* Simplify `cleanupEntries`' query
|
||||
- `NOT (hash=ANY(%4))` can be expressed as `hash NOT IN $4`
|
||||
- There is no need for a subquery operating on the same table, moving the conditions out is equivalent.
|
||||
* Reformat `ArchiveEntries`'s query for consistency's sake and replace the `=ANY` with an `IN`
|
||||
* Reformat the query in `GetEntryIDs` and `GetReadTime`'s query for consistency's sake
|
||||
* Simplify `WeeklyFeedEntryCount`: No need for a `BETWEEN`: we want to filter on entries published in the last week, no need to express is as "entries published between now and last week", "entries published after last week" is enough
|
||||
* Add some tests for `add_image_title`
|
||||
* Remove `github.com/google/uuid` dependencies: Replace it with a hand-rolled implementation. Heck, an UUID isn't even a requirement according to Omnivore API docs
|
||||
* Simplify `internal/reader/icon/finder.go`:
|
||||
- Use a simple regex to parse data uri instead of a hand-rolled parser, and document what fields are considered mandatory.
|
||||
- Use case-insensitive matching to find (fav)icons, instead of doing the same query twice with different letter cases
|
||||
- Add `apple-touch-icon-precomposed.png` as a fallback `favicon`
|
||||
- Reorder the queries to have `icon` first, since it seems to be the most popular one. It used to be last, meaning that pages had to be parsed completely 4 times, instead of one now.
|
||||
- Minor factorisation in `findIconURLsFromHTMLDocument`
|
||||
* Small refactoring of `internal/reader/date/parser.go`:
|
||||
- Split dates formats into those that require local times and those who don't, so that there is no need to have a switch-case in the for loop with around 250 iterations at most.
|
||||
- Be more strict when it comes to timezones, previously invalid ones like -13 were accepted. Also add a test for this.
|
||||
- Bail out early if the date is an empty string.
|
||||
* Make use of Go ≥ 1.21 slices package instead of hand-rolled loops
|
||||
* Reorder the fields of the `Entry` struct to save some memory
|
||||
* Dependencies update:
|
||||
* Bump `golang.org/x/oauth2` from `0.17.0` to `0.18.0`
|
||||
* Bump `github.com/prometheus/client_golang` from `1.18.0` to `1.19.0`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.16` to `2.20.18`
|
||||
* Bump `github.com/PuerkitoBio/goquery` from `1.8.1` to `1.9.1`
|
||||
* Bump `golang.org/x/crypto` from `0.19.0` to `0.20.0`
|
||||
* Bump `github.com/go-jose/go-jose/v3` from `3.0.1` to `3.0.3`
|
||||
|
||||
Version 2.1.0 (February 17, 2024)
|
||||
---------------------------------
|
||||
|
||||
* Add Linkwarden integration
|
||||
* Add LinkAce integration
|
||||
* Add `FORCE_REFRESH_INTERVAL` config option
|
||||
* Add `item-meta-info-reading-time` CSS class
|
||||
* Add `add_dynamic_iframe` rewrite function
|
||||
* Add attribute `data-original-mos` to `add_dynamic_image` rewrite candidates
|
||||
* Update entry processor to allow blocking/keeping entries by tags and/or authors
|
||||
* Change default `Accept` header when fetching feeds
|
||||
* Rewrite relative RSS Bridge URL to absolute URL
|
||||
* Use numeric user ID in Alpine and distroless container image (avoid `securityContext` error in Kubernetes)
|
||||
* Always try to use HTTP/2 when fetching feeds if available
|
||||
* Add `type` attribute in OPML export as per OPML 2.0 specs
|
||||
* Fix missing translation argument for the key `error.unable_to_parse_feed`
|
||||
* Fix Debian package builder when using Go 1.22 and `armhf` architecture
|
||||
* Fix typo in log message
|
||||
* Fix incorrect label shown when saving an article
|
||||
* Fix incorrect condition in refresh feeds cli
|
||||
* Fix incorrect label `for` attribute
|
||||
* Add missing label ID for custom CSS field
|
||||
* Accessibility improvements:
|
||||
* Add workaround for macOS VoiceOver that didn't announce `details` and `summary` when expanded
|
||||
* Add `alert` role to alert message element
|
||||
* Add a `h2` heading to the article element so that the screen reader users can navigate the article through the heading level
|
||||
* Add an `aria-label` attribute for the article element for screen readers
|
||||
* Remove the icon image `alt` attribute in feeds list to prevent screen reader to announce it before entry title
|
||||
* Add `sr-only` CSS class for screen reader users (provides more context)
|
||||
* Differentiate between buttons and links
|
||||
* Change links that could perform actions to buttons
|
||||
* Improve translation of hidden Aria elements
|
||||
* Remove the redundant article role
|
||||
* Add a search landmark for the search form so that the screen reader users can navigate to it
|
||||
* Add skip to content link
|
||||
* Add `nav` landmark to page header links
|
||||
* Limit feed/category entry pagination to unread entries when coming from unread entry list
|
||||
* Update German translation
|
||||
* Update GitHub Actions to Go 1.22
|
||||
* Bump `golang.org/x/term` from `0.16.0` to `0.17.0`
|
||||
* Bump `github.com/google/uuid` from `1.5.0` to `1.6.0`
|
||||
* Bump `github.com/yuin/goldmark` from `1.6.0` to `1.7.0`
|
||||
* Bump `golang.org/x/oauth2` from `0.15.0` to `0.17.0`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.10` to `2.20.12`
|
||||
* Bump `golang.org/x/term` from `0.15.0` to `0.16.0`
|
||||
* Bump `github.com/prometheus/client_golang` from `1.17.0` to `1.18.0`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.9` to `2.20.16`
|
||||
* Bump `golang.org/x/crypto` from `0.16.0` to `0.19.0`
|
||||
* Bump `github.com/go-webauthn/webauthn` from `0.9.4` to` 0.10.1`
|
||||
* Bump `golang.org/x/net` from `0.20.0` to `0.21.0`
|
||||
|
||||
Version 2.0.51 (December 13, 2023)
|
||||
----------------------------------
|
||||
|
||||
* Add Omnivore integration
|
||||
* Fixes for the regressions introduced in version 2.0.50:
|
||||
* Ensure all HTML documents are encoded in UTF-8
|
||||
* Send default User-Agent and HTTP caching headers when making HTTP requests
|
||||
* Allow Youtube links to be opened outside the `iframe` (avoid `ERR_BLOCKED_BY_RESPONSE` error)
|
||||
* Fix inaccessible metrics endpoint when listening on Unix socket
|
||||
* Allow renaming and moving feed at the same time in the Google Reader API
|
||||
* Log `nb_jobs` only when number of jobs is larger than 0 in background scheduler
|
||||
* Deduplicate feed URLs when parsing HTML document during discovery process
|
||||
* Calculate a virtual weekly count based on the average updating frequency (`POLLING_SCHEDULER=entry_frequency`)
|
||||
* Update GitHub Actions workflow to be able to run the linter and tests on-demand
|
||||
* Add `SCHEDULER_ROUND_ROBIN_MIN_INTERVAL` config option
|
||||
* Add links to GitHub for the commit hash and the version in the about page
|
||||
* Use "starred" rather than "bookmarked" in English translation
|
||||
* Update Chinese (CN & TW) translation
|
||||
* Bump `github.com/google/uuid` from `1.4.0` to `1.5.0`
|
||||
* Bump `github.com/coreos/go-oidc/v3` from `3.7.0` to `3.9.0`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.20.6` to `2.20.9`
|
||||
* Bump `github.com/go-webauthn/webauthn` from `0.8.6` to `0.9.4`
|
||||
* Bump `golang.org/x/oauth2` from `0.14.0` to `0.15.0`
|
||||
|
||||
Version 2.0.50 (November 12, 2023)
|
||||
----------------------------------
|
||||
|
||||
* Add WebAuthn / Passkey integration
|
||||
* Add RSS-Bridge integration
|
||||
* Take RSS TTL field into consideration to schedule next check date
|
||||
* Show number of visible entries instead of number of read entries in feed list
|
||||
* OpenID Connect: Redirect to configured user home page after successful authentication
|
||||
* Google Reader API fixes:
|
||||
* `user/{userID}/state/com.google/read` is missing in categories section for read entries
|
||||
* Take `ExcludeTargets` into consideration in feed stream handler
|
||||
* Allow iframes pointing to Twitch videos
|
||||
* Filter feed entries based on URL or title
|
||||
* Take into consideration `hide_globally` property defined for categories in `/v1/entries` API endpoint
|
||||
* Add category ID to webhooks request body
|
||||
* Update date parser to parse more invalid date formats
|
||||
* Refactor feed discovery handler, and avoid an extra HTTP request if the URL provided is the feed
|
||||
* Refactor HTTP Client and `LocalizedError` packages
|
||||
* Refactor Batch Builder, and prevent accidental and excessive refreshes from the web UI
|
||||
* Refactor icon finder:
|
||||
- Continue the discovery process when the feed icon is invalid
|
||||
- Search all icons from the HTML document and do not stop on the first one
|
||||
* Add support for SVG icons with data URL without encoding
|
||||
* Expose `next_check_at` in the web ui and API
|
||||
* Add database indexes to improve performance
|
||||
* Change log level to warning for failed feeds refresh in cronjob
|
||||
* Do not log website without icon as warning
|
||||
* Add GitHub workflow to build binaries
|
||||
* Add GitHub extensions to devcontainer
|
||||
* Make sure to pull the latest base image when building the Docker image
|
||||
* Strip version prefix when building Debian package
|
||||
* Add `github-cli` and `docker-outside-of-docker` features to devcontainer
|
||||
* Bump `golang.org/x/*` dependencies
|
||||
* Bump `github.com/gorilla/mux` from `1.8.0` to `1.8.1`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.19.9` to `2.20.6`
|
||||
* Bump `github.com/yuin/goldmark` from `1.5.6` to `1.6.0`
|
||||
* Bump `github.com/coreos/go-oidc/v3` from `3.6.0` to `3.7.0`
|
||||
|
||||
Version 2.0.49 (October 15, 2023)
|
||||
---------------------------------
|
||||
|
||||
* Implement structured logging using `log/slog` package. New config options available:
|
||||
* `LOG_FORMAT`: `json` or `text`
|
||||
* `LOG_LEVEL`: `debug`, `info`, `warning`, or `error`
|
||||
* `LOG_FILE`: `sdterr`, `stdout`, or a file path
|
||||
* The `DEBUG` option is now deprecated in favor of `LOG_LEVEL`
|
||||
* API Improvements:
|
||||
* Add endpoint `/v1/version`
|
||||
* Add endpoint `PUT /v1/entries` to update entry title and content
|
||||
* Add endpoint `/v1/icons/{iconID}`
|
||||
* Add endpoint `/v1/flush-history` to flush history
|
||||
* Make the category optional when creating feeds for API clients who don't support categories
|
||||
* Add enclosures to `GET /v1/entries` endpoint
|
||||
* Add `published_after`, `published_before`, `changed_after` and `changed_before` options to `/v1/entries` endpoint
|
||||
* Telegram integration improvements:
|
||||
* Replace feed HTML link with a button to avoid page preview issues
|
||||
* Add the possibility to disable buttons
|
||||
* Add Bruno Miniflux API collection in `contrib` folder (Bruno is an open source alternative to Postman/Insomnia)
|
||||
* Add command line argument to export user feeds as OPML
|
||||
* Add new rewrite rules `add_hn_links_using_hack` and `add_hn_links_using_opener` to open HN comments with iOS apps
|
||||
* Fix timestamp format for `Expires` response header
|
||||
* Fix Javascript error when reading time option is disabled
|
||||
* Fix Apprise logic to handle feed service URLs
|
||||
* Fix missing word in force refresh message
|
||||
* Remove deprecated `PreferServerCipherSuites` TLS option
|
||||
* Replace `github.com/rylans/getlang` with `github.com/abadojack/whatlanggo` because `getlang` doesn't seems to be updated anymore
|
||||
* Bump `github.com/mccutchen/go-httpbin/v2` from `2.11.0` to `2.11.1`
|
||||
* Bump `golang.org/x/*` dependencies
|
||||
|
||||
Version 2.0.48 (September 15, 2023)
|
||||
-----------------------------------
|
||||
|
||||
* Add generic webhook integration
|
||||
* Send webhook events when new entries are detected
|
||||
* Send wehbook events when saving an entry
|
||||
* Sign the outgoing requests with HMAC-SHA256
|
||||
* Improve Telegram integration
|
||||
* Add built-in Telegram client
|
||||
* Remove dependency on `go-telegram-bot-api` library
|
||||
* Add new options:
|
||||
* Optional topic ID
|
||||
* Disable page preview
|
||||
* Disable notifications
|
||||
* Add new button to go to article
|
||||
* Improve Matrix integration
|
||||
* Add built-in Matrix client
|
||||
* Remove dependency on `gomatrix` library
|
||||
* Send HTML formatted messages to Matrix
|
||||
* OpenID Connect authentication improvements:
|
||||
* Add OAuth2 PKCE support
|
||||
* Add `profile` scope to OIDC integration to support accounts without email address
|
||||
* Prevent empty username when using the OIDC integration
|
||||
* Add `factor` for `entry_frequency` scheduler:
|
||||
* Allow the user to increase the frequency of the `entry_frequency`
|
||||
scheduler by a configurable factor in order to shorten the time between
|
||||
updates.
|
||||
* Fix: status bar is unreadable when using PWA in dark mode on Firefox Android
|
||||
* Group form fields into fieldsets to improve page layout
|
||||
* Update Russian translation
|
||||
* Make sure icon URLs are always absolute
|
||||
* Add Apprise service URLs per feed
|
||||
* Trim `username` and `password` form fields
|
||||
* Strip HTML tags from DublinCore Creator tags
|
||||
* Fix scroll up behavior on Firefox Android
|
||||
* Add missing `return` statement in `fetchContent` UI handler
|
||||
* Add `replace_title` rewrite rule to adjust entry titles
|
||||
* Fix Pocket integration redirect URL and Google Reader API HREF
|
||||
* Fix feed `hide_globally` property to use it with third-party clients.
|
||||
|
||||
Version 2.0.47 (August 20, 2023)
|
||||
--------------------------------
|
||||
|
||||
* Update rules for `webtoons.com`
|
||||
* Use HTTP client from the standard library for third-party integrations
|
||||
* Rename internal `url` package to `urllib` to avoid overlap with `net/url`
|
||||
* Add Shaarli integration
|
||||
* Add Shiori integration
|
||||
* Add Apprise integration
|
||||
* Add Readwise Reader integration
|
||||
* Consider base path when generating third-party services API endpoint
|
||||
* Use podcast duration tag as reading time
|
||||
* Move internal packages to an `internal` folder
|
||||
* For reference: <https://go.dev/doc/go1.4#internalpackages>
|
||||
* Rename Miniflux package name to follow Go module naming convention
|
||||
* For reference: <https://go.dev/ref/mod#major-version-suffixes>
|
||||
* Update RockyLinux image from 8 to 9 (used to build RPM package)
|
||||
* Add force refresh in feed edit and feed entries page
|
||||
* Use Odysee video duration as read time
|
||||
* Upgrade to Go 1.21
|
||||
* Use details disclosure element to show the list of third-party services
|
||||
* Use Web Share API for sharing entry
|
||||
* Add a workaround for parsing some invalid date format
|
||||
* Add Thunder Client API collection into contrib folder
|
||||
* Add new API endpoint: `/entries/{entryID}/save`
|
||||
* Trigger Docker and packages workflows only for semantic tags
|
||||
* Go module versioning expect Git tags to start with the letter v.
|
||||
* The goal is to keep the existing naming convention for generated artifacts and
|
||||
have proper versioning for the Go module.
|
||||
* Bump `golang.org/x/*` dependencies
|
||||
* Bump `github.com/yuin/goldmark`
|
||||
* Bump `github.com/tdewolff/minify/v2`
|
||||
* Bump `github.com/mccutchen/go-httpbin/v2`
|
||||
|
||||
Version 2.0.46 (July 21, 2023)
|
||||
------------------------------
|
||||
|
||||
* Add scraper and rewrite rules for Webtoons
|
||||
* Fix regression in integration page and simplify SQL query
|
||||
* Wallabag integration: add more information in log messages
|
||||
* Add support for custom Youtube embed URL
|
||||
* Fix accessibility issues in modal component
|
||||
* Fix modal aria role
|
||||
* Trap focusing with tab / shift+tab inside the modal
|
||||
* Restore keyboard focus when closing modal
|
||||
* Automatically move keyboard focus to first focusable element unless specified otherwise
|
||||
* Keyboard shortcut help modal: move keyboard focus to modal title
|
||||
* Keyboard shortcut help modal: change close control from link to button
|
||||
* Add Notion integration
|
||||
* Update `golang.org/x/*` dependencies and `go-oidc` to v3.6.0
|
||||
* Improve responsive design
|
||||
* Add user setting for marking entry as read on view
|
||||
* Improve Russian translation
|
||||
* Add the possibility to run cleanup tasks from the command line
|
||||
* Add the possibility to run Miniflux as a cronjob
|
||||
* Use `go-httpbin` to run tests locally and avoid remote calls to `httpbin.org`
|
||||
* Display tags when viewing entries
|
||||
* Update categories API endpoint to return `total_unread` and `feed_count`
|
||||
* Improve date parser to handle various broken date formats
|
||||
* Avoid `pq: time zone displacement out of range` errors
|
||||
* Improve entry existance check to make better use of index
|
||||
* Add unique index `enclosures_user_entry_url_idx`
|
||||
* Add mark as unread for Linkding integration
|
||||
* Add sub-folder support for Wallabag integration
|
||||
* Use RockyLinux to build RPM package
|
||||
* Disable CGO when building RPM package
|
||||
* Disable CGO when building Docker images
|
||||
|
||||
Version 2.0.45 (June 21, 2023)
|
||||
------------------------------
|
||||
|
||||
* Add media player to listen to audio and video podcasts with the possiblity to resume to last playback position
|
||||
* Add default tag names for Linkding integration
|
||||
* Mark only globally visible entries when marking all entries from UI
|
||||
* Use image included in feed as feed icon when available
|
||||
* Order history by `changed_at` and `published_at`
|
||||
* Remove title attribute from entry title links
|
||||
* Fix reading time that is not aligned correctly with the latest version of Safari
|
||||
* Use glyphs of the same size on keyboard shortcuts page
|
||||
* Add maskable versions of the PWA icon
|
||||
* Replace copyright header with SPDX identifier
|
||||
* Remove the "í" letter from the Portuguese "lido" word
|
||||
* Increase golangci-lint timeout value
|
||||
* Bump `github.com/tdewolff/minify/v2`, `github.com/prometheus/client_golang`, `golang.org/x/*` dependencies
|
||||
|
||||
Version 2.0.44 (May 6, 2023)
|
||||
----------------------------
|
||||
|
||||
* Add link to the URL rewrite rules documentation
|
||||
* Update scraping rules for `ilpost.it`
|
||||
* Update rewrite rules for `theverge.com`
|
||||
* Add a rewrite rule to remove clickbait titles
|
||||
* Make sure `PROXY_IMAGES` option is backward compatible with `PROXY_OPTION` and `PROXY_MEDIA_TYPES`
|
||||
* Add new rule to remove tables
|
||||
* Add support for searching well-known URLs in subdirectory
|
||||
* Add CSS `word-wrap` rule to break very long entry title into multiple lines
|
||||
* Add swipe as option for gesture navigation between entries. There are now 3 possible choices: `none`, `double-tap`, and `swipe`.
|
||||
* Prefer typographic punctuation in English translation
|
||||
* Process older entries first:
|
||||
- Feed entries are usually ordered from most to least recent.
|
||||
- Processing older entries first ensures that their creation timestamp
|
||||
is lower than that of newer entries.
|
||||
- This is useful when we order by creation, because then we get a
|
||||
consistent timeline.
|
||||
* Fix Grafana dashboard
|
||||
* Push Docker images to `Quay.io` (RedHat)
|
||||
* Bump `golang.org/x/*`, `github.com/lib/pq`, `mvdan.cc/xurls/v2` and `github.com/prometheus/client_golang` dependencies
|
||||
|
||||
Version 2.0.43 (March 16, 2023)
|
||||
-------------------------------
|
||||
|
||||
* Avoid XSS when opening a broken image due to unescaped ServerError in proxy handler (CVE-2023-27592)
|
||||
|
||||
Creating an RSS feed item with the inline description containing an `<img>` tag
|
||||
with a `srcset` attribute pointing to an invalid URL like
|
||||
`http:a<script>alert(1)</script>`, we can coerce the proxy handler into an error
|
||||
condition where the invalid URL is returned unescaped and in full.
|
||||
|
||||
This results in JavaScript execution on the Miniflux instance as soon as the
|
||||
user is convinced to open the broken image.
|
||||
|
||||
* Use `r.RemoteAddr` to check `/metrics` endpoint network access (CVE-2023-27591)
|
||||
|
||||
HTTP headers like `X-Forwarded-For` or `X-Real-Ip` can be easily spoofed. As
|
||||
such, it cannot be used to test if the client IP is allowed.
|
||||
|
||||
The recommendation is to use HTTP Basic authentication to protect the
|
||||
metrics endpoint, or run Miniflux behind a trusted reverse-proxy.
|
||||
|
||||
* Add HTTP Basic authentication for `/metrics` endpoint
|
||||
* Add proxy support for several media types
|
||||
* Parse feed categories from RSS, Atom and JSON feeds
|
||||
* Ignore empty link when discovering feeds
|
||||
* Disable CGO explicitly to make sure the binary is statically linked
|
||||
* Add CSS classes to differentiate between category/feed/entry view and icons
|
||||
* Add rewrite and scraper rules for `blog.cloudflare.com`
|
||||
* Add `color-scheme` to themes
|
||||
* Add new keyboard shortcut to toggle open/close entry attachments section
|
||||
* Sanitizer: allow `id` attribute in `<sup>` element
|
||||
* Add Indonesian Language
|
||||
* Update translations
|
||||
* Update Docker Compose examples:
|
||||
- Run the application in one command
|
||||
- Bring back the health check condition to `depends_on`
|
||||
- Remove deprecated `version` element
|
||||
* Update scraping rules for `ilpost.it`
|
||||
* Bump `github.com/PuerkitoBio/goquery` from `1.8.0` to `1.8.1`
|
||||
* Bump `github.com/tdewolff/minify/v2` from `2.12.4` to `2.12.5`
|
||||
* Bump `github.com/yuin/goldmark` from `1.5.3` to `1.5.4`
|
||||
* Bump `golang.org/x/*` dependencies
|
||||
|
||||
Version 2.0.42 (January 29, 2023)
|
||||
---------------------------------
|
||||
|
||||
* Fix header items wrapping
|
||||
* Add option to enable or disable double tap
|
||||
* Improve PWA display mode label in settings page
|
||||
* Bump `golang.org/x/*` dependencies
|
||||
* Update translations
|
||||
* Add scraping rule for `ilpost.it`
|
||||
* Update reading time HTML element after fetching the original web page
|
||||
* Add category feeds refresh feature
|
||||
|
||||
Version 2.0.41 (December 10, 2022)
|
||||
----------------------------------
|
||||
|
||||
* Reverted PR #1290 (follow the only link) because it leads to several panics/segfaults that prevent feed updates
|
||||
* Disable double-tap mobile gesture if swipe gesture is disabled
|
||||
* Skip integrations if there are no entries to push
|
||||
* Enable TLS-ALPN-01 challenge for ACME
|
||||
- This type of challenge works purely at the TLS layer and is compatible
|
||||
with SNI proxies. The existing HTTP-01 challenge support has been left
|
||||
as-is.
|
||||
* Preconfigure Miniflux for GitHub Codespaces
|
||||
* Updated `golang.org/x/net/*` dependencies
|
||||
|
||||
Version 2.0.40 (November 13, 2022)
|
||||
----------------------------------
|
||||
|
||||
* Update dependencies
|
||||
* Pin Postgres image version in Docker Compose examples to avoid unexpected upgrades
|
||||
* Make English and Spanish translation more consistent:
|
||||
- Use "Feed" everywhere instead of "Subscription"
|
||||
- Use "Entry" instead of "Article"
|
||||
* Allow Content-Type and Accept headers in CORS policy
|
||||
* Use dirs file for Debian package
|
||||
* Use custom home page in PWA manifest
|
||||
* Fix scraper rule that could be incorrect when there is a redirect
|
||||
* Improve web scraper to fetch the only link present as workaround to some landing pages
|
||||
* Add Matrix bot integration
|
||||
* Proxify images in API responses
|
||||
* Add new options in user preferences to configure sorting of entries in the category page
|
||||
* Remove dependency on `github.com/mitchellh/go-server-timing`
|
||||
* Add support for the `continuation` parameter and result for Google Reader API ID calls
|
||||
* Use automatic variable for build target file names
|
||||
* Add rewrite rule for `recalbox.com`
|
||||
* Improve Dutch translation
|
||||
|
||||
Version 2.0.39 (October 16, 2022)
|
||||
---------------------------------
|
||||
|
||||
|
|
88
Makefile
88
Makefile
|
@ -1,17 +1,18 @@
|
|||
APP := miniflux
|
||||
DOCKER_IMAGE := miniflux/miniflux
|
||||
VERSION := $(shell git describe --tags --abbrev=0)
|
||||
COMMIT := $(shell git rev-parse --short HEAD)
|
||||
BUILD_DATE := `date +%FT%T%z`
|
||||
LD_FLAGS := "-s -w -X 'miniflux.app/version.Version=$(VERSION)' -X 'miniflux.app/version.Commit=$(COMMIT)' -X 'miniflux.app/version.BuildDate=$(BUILD_DATE)'"
|
||||
PKG_LIST := $(shell go list ./... | grep -v /vendor/)
|
||||
DB_URL := postgres://postgres:postgres@localhost/miniflux_test?sslmode=disable
|
||||
DEB_IMG_ARCH := amd64
|
||||
APP := miniflux
|
||||
DOCKER_IMAGE := miniflux/miniflux
|
||||
VERSION := $(shell git describe --tags --abbrev=0 2>/dev/null)
|
||||
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)
|
||||
BUILD_DATE := `date +%FT%T%z`
|
||||
LD_FLAGS := "-s -w -X 'miniflux.app/v2/internal/version.Version=$(VERSION)' -X 'miniflux.app/v2/internal/version.Commit=$(COMMIT)' -X 'miniflux.app/v2/internal/version.BuildDate=$(BUILD_DATE)'"
|
||||
PKG_LIST := $(shell go list ./... | grep -v /vendor/)
|
||||
DB_URL := postgres://postgres:postgres@localhost/miniflux_test?sslmode=disable
|
||||
DOCKER_PLATFORM := amd64
|
||||
|
||||
export PGPASSWORD := postgres
|
||||
|
||||
.PHONY: \
|
||||
miniflux \
|
||||
miniflux-no-pie \
|
||||
linux-amd64 \
|
||||
linux-arm64 \
|
||||
linux-armv7 \
|
||||
|
@ -45,68 +46,73 @@ export PGPASSWORD := postgres
|
|||
miniflux:
|
||||
@ go build -buildmode=pie -ldflags=$(LD_FLAGS) -o $(APP) main.go
|
||||
|
||||
miniflux-no-pie:
|
||||
@ go build -ldflags=$(LD_FLAGS) -o $(APP) main.go
|
||||
|
||||
linux-amd64:
|
||||
@ GOOS=linux GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-amd64 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
linux-arm64:
|
||||
@ GOOS=linux GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-arm64 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
linux-armv7:
|
||||
@ GOOS=linux GOARCH=arm GOARM=7 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-armv7 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
linux-armv6:
|
||||
@ GOOS=linux GOARCH=arm GOARM=6 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-armv6 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
linux-armv5:
|
||||
@ GOOS=linux GOARCH=arm GOARM=5 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-armv5 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
darwin-amd64:
|
||||
@ GOOS=darwin GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-darwin-amd64 main.go
|
||||
@ GOOS=darwin GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
darwin-arm64:
|
||||
@ GOOS=darwin GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-darwin-arm64 main.go
|
||||
@ GOOS=darwin GOARCH=arm64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
freebsd-amd64:
|
||||
@ GOOS=freebsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-freebsd-amd64 main.go
|
||||
@ CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
openbsd-amd64:
|
||||
@ GOOS=openbsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-openbsd-amd64 main.go
|
||||
@ GOOS=openbsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
windows-amd64:
|
||||
@ GOOS=windows GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-windows-amd64 main.go
|
||||
@ GOOS=windows GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@.exe main.go
|
||||
|
||||
build: linux-amd64 linux-arm64 linux-armv7 linux-armv6 linux-armv5 darwin-amd64 darwin-arm64 freebsd-amd64 openbsd-amd64 windows-amd64
|
||||
|
||||
# NOTE: unsupported targets
|
||||
netbsd-amd64:
|
||||
@ GOOS=netbsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-netbsd-amd64 main.go
|
||||
@ CGO_ENABLED=0 GOOS=netbsd GOARCH=amd64 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
linux-x86:
|
||||
@ GOOS=linux GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-linux-x86 main.go
|
||||
@ CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
freebsd-x86:
|
||||
@ GOOS=freebsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-freebsd-x86 main.go
|
||||
@ CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
netbsd-x86:
|
||||
@ GOOS=netbsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-netbsd-x86 main.go
|
||||
@ CGO_ENABLED=0 GOOS=netbsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
openbsd-x86:
|
||||
@ GOOS=openbsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-freebsd-x86 main.go
|
||||
@ GOOS=openbsd GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@ main.go
|
||||
|
||||
windows-x86:
|
||||
@ GOOS=windows GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-windows-x86 main.go
|
||||
@ GOOS=windows GOARCH=386 go build -ldflags=$(LD_FLAGS) -o $(APP)-$@.exe main.go
|
||||
|
||||
run:
|
||||
@ LOG_DATE_TIME=1 DEBUG=1 RUN_MIGRATIONS=1 go run main.go
|
||||
@ LOG_DATE_TIME=1 LOG_LEVEL=debug RUN_MIGRATIONS=1 CREATE_ADMIN=1 ADMIN_USERNAME=admin ADMIN_PASSWORD=test123 go run main.go
|
||||
|
||||
clean:
|
||||
@ rm -f $(APP)-* $(APP) $(APP)*.rpm $(APP)*.deb
|
||||
@ rm -f $(APP)-* $(APP) $(APP)*.rpm $(APP)*.deb $(APP)*.exe
|
||||
|
||||
test:
|
||||
go test -cover -race -count=1 ./...
|
||||
|
||||
lint:
|
||||
golint -set_exit_status ${PKG_LIST}
|
||||
go vet ./...
|
||||
staticcheck ./...
|
||||
golangci-lint run --disable errcheck --enable sqlclosecheck --enable misspell --enable gofmt --enable goimports --enable whitespace
|
||||
|
||||
integration-test:
|
||||
psql -U postgres -c 'drop database if exists miniflux_test;'
|
||||
|
@ -120,9 +126,13 @@ integration-test:
|
|||
RUN_MIGRATIONS=1 \
|
||||
DEBUG=1 \
|
||||
./miniflux-test >/tmp/miniflux.log 2>&1 & echo "$$!" > "/tmp/miniflux.pid"
|
||||
|
||||
|
||||
while ! nc -z localhost 8080; do sleep 1; done
|
||||
go test -v -tags=integration -count=1 miniflux.app/tests
|
||||
|
||||
TEST_MINIFLUX_BASE_URL=http://127.0.0.1:8080 \
|
||||
TEST_MINIFLUX_ADMIN_USERNAME=admin \
|
||||
TEST_MINIFLUX_ADMIN_PASSWORD=test123 \
|
||||
go test -v -count=1 ./internal/api
|
||||
|
||||
clean-integration-test:
|
||||
@ kill -9 `cat /tmp/miniflux.pid`
|
||||
|
@ -131,7 +141,7 @@ clean-integration-test:
|
|||
@ psql -U postgres -c 'drop database if exists miniflux_test;'
|
||||
|
||||
docker-image:
|
||||
docker build -t $(DOCKER_IMAGE):$(VERSION) -f packaging/docker/alpine/Dockerfile .
|
||||
docker build --pull -t $(DOCKER_IMAGE):$(VERSION) -f packaging/docker/alpine/Dockerfile .
|
||||
|
||||
docker-image-distroless:
|
||||
docker build -t $(DOCKER_IMAGE):$(VERSION) -f packaging/docker/distroless/Dockerfile .
|
||||
|
@ -153,15 +163,15 @@ rpm: clean
|
|||
rpmbuild -bb --define "_miniflux_version $(VERSION)" /root/rpmbuild/SPECS/miniflux.spec
|
||||
|
||||
debian:
|
||||
@ docker build --load \
|
||||
--build-arg BASE_IMAGE_ARCH=$(DEB_IMG_ARCH) \
|
||||
-t $(DEB_IMG_ARCH)/miniflux-deb-builder \
|
||||
@ docker buildx build --load \
|
||||
--platform linux/$(DOCKER_PLATFORM) \
|
||||
-t miniflux-deb-builder \
|
||||
-f packaging/debian/Dockerfile \
|
||||
.
|
||||
@ docker run --rm \
|
||||
-v ${PWD}:/pkg $(DEB_IMG_ARCH)/miniflux-deb-builder
|
||||
@ docker run --rm --platform linux/$(DOCKER_PLATFORM) \
|
||||
-v ${PWD}:/pkg miniflux-deb-builder
|
||||
|
||||
debian-packages: clean
|
||||
$(MAKE) debian DEB_IMG_ARCH=amd64
|
||||
$(MAKE) debian DEB_IMG_ARCH=arm64v8
|
||||
$(MAKE) debian DEB_IMG_ARCH=arm32v7
|
||||
$(MAKE) debian DOCKER_PLATFORM=amd64
|
||||
$(MAKE) debian DOCKER_PLATFORM=arm64
|
||||
$(MAKE) debian DOCKER_PLATFORM=arm/v7
|
||||
|
|
|
@ -6,4 +6,6 @@ Only the latest stable version is supported.
|
|||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Send an email to `security AT miniflux DOT net` with all the steps to reproduce the problem.
|
||||
Preferably, [report the vulnerability privately using GitHub](https://github.com/miniflux/v2/security/advisories/new) ([documentation](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability)).
|
||||
|
||||
If you do not want to use GitHub, send an email to `security AT miniflux DOT net` with all the steps to reproduce the problem.
|
||||
|
|
38
api/icon.go
38
api/icon.go
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2017 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package api // import "miniflux.app/api"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"miniflux.app/http/request"
|
||||
"miniflux.app/http/response/json"
|
||||
)
|
||||
|
||||
func (h *handler) feedIcon(w http.ResponseWriter, r *http.Request) {
|
||||
feedID := request.RouteInt64Param(r, "feedID")
|
||||
|
||||
if !h.store.HasIcon(feedID) {
|
||||
json.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
icon, err := h.store.IconByFeedID(request.UserID(r), feedID)
|
||||
if err != nil {
|
||||
json.ServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if icon == nil {
|
||||
json.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
json.OK(w, r, &feedIconResponse{
|
||||
ID: icon.ID,
|
||||
MimeType: icon.MimeType,
|
||||
Data: icon.DataURL(),
|
||||
})
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2017 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package api // import "miniflux.app/api"
|
||||
|
||||
import (
|
||||
"miniflux.app/model"
|
||||
)
|
||||
|
||||
type feedIconResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
MimeType string `json:"mime_type"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type entriesResponse struct {
|
||||
Total int `json:"total"`
|
||||
Entries model.Entries `json:"entries"`
|
||||
}
|
||||
|
||||
type feedCreationResponse struct {
|
||||
FeedID int64 `json:"feed_id"`
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright 2017 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package api // import "miniflux.app/api"
|
||||
|
||||
import (
|
||||
json_parser "encoding/json"
|
||||
"net/http"
|
||||
|
||||
"miniflux.app/http/response/json"
|
||||
"miniflux.app/model"
|
||||
"miniflux.app/reader/subscription"
|
||||
"miniflux.app/validator"
|
||||
)
|
||||
|
||||
func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request) {
|
||||
var subscriptionDiscoveryRequest model.SubscriptionDiscoveryRequest
|
||||
if err := json_parser.NewDecoder(r.Body).Decode(&subscriptionDiscoveryRequest); err != nil {
|
||||
json.BadRequest(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if validationErr := validator.ValidateSubscriptionDiscovery(&subscriptionDiscoveryRequest); validationErr != nil {
|
||||
json.BadRequest(w, r, validationErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
subscriptions, finderErr := subscription.FindSubscriptions(
|
||||
subscriptionDiscoveryRequest.URL,
|
||||
subscriptionDiscoveryRequest.UserAgent,
|
||||
subscriptionDiscoveryRequest.Cookie,
|
||||
subscriptionDiscoveryRequest.Username,
|
||||
subscriptionDiscoveryRequest.Password,
|
||||
subscriptionDiscoveryRequest.FetchViaProxy,
|
||||
subscriptionDiscoveryRequest.AllowSelfSignedCertificates,
|
||||
)
|
||||
if finderErr != nil {
|
||||
json.ServerError(w, r, finderErr)
|
||||
return
|
||||
}
|
||||
|
||||
if subscriptions == nil {
|
||||
json.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
json.OK(w, r, subscriptions)
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cli // import "miniflux.app/cli"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"miniflux.app/config"
|
||||
"miniflux.app/logger"
|
||||
"miniflux.app/model"
|
||||
"miniflux.app/storage"
|
||||
"miniflux.app/validator"
|
||||
)
|
||||
|
||||
func createAdmin(store *storage.Storage) {
|
||||
userCreationRequest := &model.UserCreationRequest{
|
||||
Username: config.Opts.AdminUsername(),
|
||||
Password: config.Opts.AdminPassword(),
|
||||
IsAdmin: true,
|
||||
}
|
||||
|
||||
if userCreationRequest.Username == "" || userCreationRequest.Password == "" {
|
||||
userCreationRequest.Username, userCreationRequest.Password = askCredentials()
|
||||
}
|
||||
|
||||
if store.UserExists(userCreationRequest.Username) {
|
||||
logger.Info(`User %q already exists, skipping creation`, userCreationRequest.Username)
|
||||
return
|
||||
}
|
||||
|
||||
if validationErr := validator.ValidateUserCreationWithPassword(store, userCreationRequest); validationErr != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", validationErr)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := store.CreateUser(userCreationRequest); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package cli implements command line arguments for Miniflux application.
|
||||
*/
|
||||
package cli // import "miniflux.app/cli"
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cli // import "miniflux.app/cli"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"miniflux.app/storage"
|
||||
)
|
||||
|
||||
func flushSessions(store *storage.Storage) {
|
||||
fmt.Println("Flushing all sessions (disconnect users)")
|
||||
if err := store.FlushAllSessions(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2021 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cli // import "miniflux.app/cli"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"miniflux.app/config"
|
||||
"miniflux.app/logger"
|
||||
)
|
||||
|
||||
func doHealthCheck(healthCheckEndpoint string) {
|
||||
if healthCheckEndpoint == "auto" {
|
||||
healthCheckEndpoint = "http://" + config.Opts.ListenAddr() + config.Opts.BasePath() + "/healthcheck"
|
||||
}
|
||||
|
||||
logger.Debug(`Executing health check on %s`, healthCheckEndpoint)
|
||||
|
||||
client := &http.Client{Timeout: 3 * time.Second}
|
||||
resp, err := client.Get(healthCheckEndpoint)
|
||||
if err != nil {
|
||||
logger.Fatal(`Health check failure: %v`, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
logger.Fatal(`Health check failed with status code %d`, resp.StatusCode)
|
||||
}
|
||||
|
||||
logger.Debug(`Health check is OK`)
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
Miniflux API Client
|
||||
===================
|
||||
|
||||
[![PkgGoDev](https://pkg.go.dev/badge/miniflux.app/client)](https://pkg.go.dev/miniflux.app/client)
|
||||
[![PkgGoDev](https://pkg.go.dev/badge/miniflux.app/v2/client)](https://pkg.go.dev/miniflux.app/v2/client)
|
||||
|
||||
Client library for Miniflux REST API.
|
||||
|
||||
|
@ -9,7 +9,7 @@ Installation
|
|||
------------
|
||||
|
||||
```bash
|
||||
go get -u miniflux.app/client
|
||||
go get -u miniflux.app/v2/client
|
||||
```
|
||||
|
||||
Example
|
||||
|
@ -22,7 +22,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
miniflux "miniflux.app/client"
|
||||
miniflux "miniflux.app/v2/client"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
222
client/client.go
222
client/client.go
|
@ -1,8 +1,7 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package client // import "miniflux.app/client"
|
||||
package client // import "miniflux.app/v2/client"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -19,16 +18,60 @@ type Client struct {
|
|||
}
|
||||
|
||||
// New returns a new Miniflux client.
|
||||
// Deprecated: use NewClient instead.
|
||||
func New(endpoint string, credentials ...string) *Client {
|
||||
// Web gives "API Endpoint = https://miniflux.app/v1/", it doesn't work (/v1/v1/me)
|
||||
return NewClient(endpoint, credentials...)
|
||||
}
|
||||
|
||||
// NewClient returns a new Miniflux client.
|
||||
func NewClient(endpoint string, credentials ...string) *Client {
|
||||
// Trim trailing slashes and /v1 from the endpoint.
|
||||
endpoint = strings.TrimSuffix(endpoint, "/")
|
||||
endpoint = strings.TrimSuffix(endpoint, "/v1")
|
||||
// trim to https://miniflux.app
|
||||
|
||||
if len(credentials) == 2 {
|
||||
switch len(credentials) {
|
||||
case 2:
|
||||
return &Client{request: &request{endpoint: endpoint, username: credentials[0], password: credentials[1]}}
|
||||
case 1:
|
||||
return &Client{request: &request{endpoint: endpoint, apiKey: credentials[0]}}
|
||||
default:
|
||||
return &Client{request: &request{endpoint: endpoint}}
|
||||
}
|
||||
return &Client{request: &request{endpoint: endpoint, apiKey: credentials[0]}}
|
||||
}
|
||||
|
||||
// Healthcheck checks if the application is up and running.
|
||||
func (c *Client) Healthcheck() error {
|
||||
body, err := c.request.Get("/healthcheck")
|
||||
if err != nil {
|
||||
return fmt.Errorf("miniflux: unable to perform healthcheck: %w", err)
|
||||
}
|
||||
defer body.Close()
|
||||
|
||||
responseBodyContent, err := io.ReadAll(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("miniflux: unable to read healthcheck response: %w", err)
|
||||
}
|
||||
|
||||
if string(responseBodyContent) != "OK" {
|
||||
return fmt.Errorf("miniflux: invalid healthcheck response: %q", responseBodyContent)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Version returns the version of the Miniflux instance.
|
||||
func (c *Client) Version() (*VersionResponse, error) {
|
||||
body, err := c.request.Get("/v1/version")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer body.Close()
|
||||
|
||||
var versionResponse *VersionResponse
|
||||
if err := json.NewDecoder(body).Decode(&versionResponse); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: json error (%v)", err)
|
||||
}
|
||||
|
||||
return versionResponse, nil
|
||||
}
|
||||
|
||||
// Me returns the logged user information.
|
||||
|
@ -40,8 +83,7 @@ func (c *Client) Me() (*User, error) {
|
|||
defer body.Close()
|
||||
|
||||
var user *User
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&user); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&user); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: json error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -57,8 +99,7 @@ func (c *Client) Users() (Users, error) {
|
|||
defer body.Close()
|
||||
|
||||
var users Users
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&users); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&users); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -74,8 +115,7 @@ func (c *Client) UserByID(userID int64) (*User, error) {
|
|||
defer body.Close()
|
||||
|
||||
var user User
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&user); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&user); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -91,8 +131,7 @@ func (c *Client) UserByUsername(username string) (*User, error) {
|
|||
defer body.Close()
|
||||
|
||||
var user User
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&user); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&user); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -112,8 +151,7 @@ func (c *Client) CreateUser(username, password string, isAdmin bool) (*User, err
|
|||
defer body.Close()
|
||||
|
||||
var user *User
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&user); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&user); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -129,8 +167,7 @@ func (c *Client) UpdateUser(userID int64, userChanges *UserModificationRequest)
|
|||
defer body.Close()
|
||||
|
||||
var u *User
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&u); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&u); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -157,8 +194,7 @@ func (c *Client) Discover(url string) (Subscriptions, error) {
|
|||
defer body.Close()
|
||||
|
||||
var subscriptions Subscriptions
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&subscriptions); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&subscriptions); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -174,8 +210,7 @@ func (c *Client) Categories() (Categories, error) {
|
|||
defer body.Close()
|
||||
|
||||
var categories Categories
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&categories); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&categories); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -193,8 +228,7 @@ func (c *Client) CreateCategory(title string) (*Category, error) {
|
|||
defer body.Close()
|
||||
|
||||
var category *Category
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&category); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&category); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -212,8 +246,7 @@ func (c *Client) UpdateCategory(categoryID int64, title string) (*Category, erro
|
|||
defer body.Close()
|
||||
|
||||
var category *Category
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&category); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&category); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -235,8 +268,7 @@ func (c *Client) CategoryFeeds(categoryID int64) (Feeds, error) {
|
|||
defer body.Close()
|
||||
|
||||
var feeds Feeds
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&feeds); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&feeds); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -248,6 +280,12 @@ func (c *Client) DeleteCategory(categoryID int64) error {
|
|||
return c.request.Delete(fmt.Sprintf("/v1/categories/%d", categoryID))
|
||||
}
|
||||
|
||||
// RefreshCategory refreshes a category.
|
||||
func (c *Client) RefreshCategory(categoryID int64) error {
|
||||
_, err := c.request.Put(fmt.Sprintf("/v1/categories/%d/refresh", categoryID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Feeds gets all feeds.
|
||||
func (c *Client) Feeds() (Feeds, error) {
|
||||
body, err := c.request.Get("/v1/feeds")
|
||||
|
@ -257,8 +295,7 @@ func (c *Client) Feeds() (Feeds, error) {
|
|||
defer body.Close()
|
||||
|
||||
var feeds Feeds
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&feeds); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&feeds); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -296,8 +333,7 @@ func (c *Client) Feed(feedID int64) (*Feed, error) {
|
|||
defer body.Close()
|
||||
|
||||
var feed *Feed
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&feed); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&feed); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -317,8 +353,7 @@ func (c *Client) CreateFeed(feedCreationRequest *FeedCreationRequest) (int64, er
|
|||
}
|
||||
|
||||
var r result
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&r); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&r); err != nil {
|
||||
return 0, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -373,8 +408,7 @@ func (c *Client) FeedIcon(feedID int64) (*FeedIcon, error) {
|
|||
defer body.Close()
|
||||
|
||||
var feedIcon *FeedIcon
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&feedIcon); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&feedIcon); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -390,8 +424,7 @@ func (c *Client) FeedEntry(feedID, entryID int64) (*Entry, error) {
|
|||
defer body.Close()
|
||||
|
||||
var entry *Entry
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&entry); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&entry); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -407,8 +440,7 @@ func (c *Client) CategoryEntry(categoryID, entryID int64) (*Entry, error) {
|
|||
defer body.Close()
|
||||
|
||||
var entry *Entry
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&entry); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&entry); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -424,8 +456,7 @@ func (c *Client) Entry(entryID int64) (*Entry, error) {
|
|||
defer body.Close()
|
||||
|
||||
var entry *Entry
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&entry); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&entry); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -443,8 +474,7 @@ func (c *Client) Entries(filter *Filter) (*EntryResultSet, error) {
|
|||
defer body.Close()
|
||||
|
||||
var result EntryResultSet
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&result); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -462,8 +492,7 @@ func (c *Client) FeedEntries(feedID int64, filter *Filter) (*EntryResultSet, err
|
|||
defer body.Close()
|
||||
|
||||
var result EntryResultSet
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&result); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -481,8 +510,7 @@ func (c *Client) CategoryEntries(categoryID int64, filter *Filter) (*EntryResult
|
|||
defer body.Close()
|
||||
|
||||
var result EntryResultSet
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&result); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
|
@ -500,13 +528,54 @@ func (c *Client) UpdateEntries(entryIDs []int64, status string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// UpdateEntry updates an entry.
|
||||
func (c *Client) UpdateEntry(entryID int64, entryChanges *EntryModificationRequest) (*Entry, error) {
|
||||
body, err := c.request.Put(fmt.Sprintf("/v1/entries/%d", entryID), entryChanges)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer body.Close()
|
||||
|
||||
var entry *Entry
|
||||
if err := json.NewDecoder(body).Decode(&entry); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// ToggleBookmark toggles entry bookmark value.
|
||||
func (c *Client) ToggleBookmark(entryID int64) error {
|
||||
_, err := c.request.Put(fmt.Sprintf("/v1/entries/%d/bookmark", entryID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// FetchCounters
|
||||
// SaveEntry sends an entry to a third-party service.
|
||||
func (c *Client) SaveEntry(entryID int64) error {
|
||||
_, err := c.request.Post(fmt.Sprintf("/v1/entries/%d/save", entryID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// FetchEntryOriginalContent fetches the original content of an entry using the scraper.
|
||||
func (c *Client) FetchEntryOriginalContent(entryID int64) (string, error) {
|
||||
body, err := c.request.Get(fmt.Sprintf("/v1/entries/%d/fetch-content", entryID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer body.Close()
|
||||
|
||||
var response struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(body).Decode(&response); err != nil {
|
||||
return "", fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
return response.Content, nil
|
||||
}
|
||||
|
||||
// FetchCounters fetches feed counters.
|
||||
func (c *Client) FetchCounters() (*FeedCounters, error) {
|
||||
body, err := c.request.Get("/v1/feeds/counters")
|
||||
if err != nil {
|
||||
|
@ -515,14 +584,35 @@ func (c *Client) FetchCounters() (*FeedCounters, error) {
|
|||
defer body.Close()
|
||||
|
||||
var result FeedCounters
|
||||
decoder := json.NewDecoder(body)
|
||||
if err := decoder.Decode(&result); err != nil {
|
||||
if err := json.NewDecoder(body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// FlushHistory changes all entries with the status "read" to "removed".
|
||||
func (c *Client) FlushHistory() error {
|
||||
_, err := c.request.Put("/v1/flush-history", nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Icon fetches a feed icon.
|
||||
func (c *Client) Icon(iconID int64) (*FeedIcon, error) {
|
||||
body, err := c.request.Get(fmt.Sprintf("/v1/icons/%d", iconID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer body.Close()
|
||||
|
||||
var feedIcon *FeedIcon
|
||||
if err := json.NewDecoder(body).Decode(&feedIcon); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: response error (%v)", err)
|
||||
}
|
||||
|
||||
return feedIcon, nil
|
||||
}
|
||||
|
||||
func buildFilterQueryString(path string, filter *Filter) string {
|
||||
if filter != nil {
|
||||
values := url.Values{}
|
||||
|
@ -551,14 +641,30 @@ func buildFilterQueryString(path string, filter *Filter) string {
|
|||
values.Set("after", strconv.FormatInt(filter.After, 10))
|
||||
}
|
||||
|
||||
if filter.AfterEntryID > 0 {
|
||||
values.Set("after_entry_id", strconv.FormatInt(filter.AfterEntryID, 10))
|
||||
}
|
||||
|
||||
if filter.Before > 0 {
|
||||
values.Set("before", strconv.FormatInt(filter.Before, 10))
|
||||
}
|
||||
|
||||
if filter.PublishedAfter > 0 {
|
||||
values.Set("published_after", strconv.FormatInt(filter.PublishedAfter, 10))
|
||||
}
|
||||
|
||||
if filter.PublishedBefore > 0 {
|
||||
values.Set("published_before", strconv.FormatInt(filter.PublishedBefore, 10))
|
||||
}
|
||||
|
||||
if filter.ChangedAfter > 0 {
|
||||
values.Set("changed_after", strconv.FormatInt(filter.ChangedAfter, 10))
|
||||
}
|
||||
|
||||
if filter.ChangedBefore > 0 {
|
||||
values.Set("changed_before", strconv.FormatInt(filter.ChangedBefore, 10))
|
||||
}
|
||||
|
||||
if filter.AfterEntryID > 0 {
|
||||
values.Set("after_entry_id", strconv.FormatInt(filter.AfterEntryID, 10))
|
||||
}
|
||||
|
||||
if filter.BeforeEntryID > 0 {
|
||||
values.Set("before_entry_id", strconv.FormatInt(filter.BeforeEntryID, 10))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
Package client implements a client library for the Miniflux REST API.
|
||||
|
@ -10,10 +9,10 @@ Package client implements a client library for the Miniflux REST API.
|
|||
This code snippet fetch the list of users:
|
||||
|
||||
import (
|
||||
miniflux "miniflux.app/client"
|
||||
miniflux "miniflux.app/v2/client"
|
||||
)
|
||||
|
||||
client := miniflux.New("https://api.example.org", "admin", "secret")
|
||||
client := miniflux.NewClient("https://api.example.org", "admin", "secret")
|
||||
users, err := client.Users()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
@ -30,4 +29,4 @@ This one discover subscriptions on a website:
|
|||
}
|
||||
fmt.Println(subscriptions)
|
||||
*/
|
||||
package client // import "miniflux.app/client"
|
||||
package client // import "miniflux.app/v2/client"
|
||||
|
|
174
client/model.go
174
client/model.go
|
@ -1,8 +1,7 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package client // import "miniflux.app/client"
|
||||
package client // import "miniflux.app/v2/client"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -18,27 +17,31 @@ const (
|
|||
|
||||
// User represents a user in the system.
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password,omitempty"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
Timezone string `json:"timezone"`
|
||||
EntryDirection string `json:"entry_sorting_direction"`
|
||||
EntryOrder string `json:"entry_sorting_order"`
|
||||
Stylesheet string `json:"stylesheet"`
|
||||
GoogleID string `json:"google_id"`
|
||||
OpenIDConnectID string `json:"openid_connect_id"`
|
||||
EntriesPerPage int `json:"entries_per_page"`
|
||||
KeyboardShortcuts bool `json:"keyboard_shortcuts"`
|
||||
ShowReadingTime bool `json:"show_reading_time"`
|
||||
EntrySwipe bool `json:"entry_swipe"`
|
||||
LastLoginAt *time.Time `json:"last_login_at"`
|
||||
DisplayMode string `json:"display_mode"`
|
||||
DefaultReadingSpeed int `json:"default_reading_speed"`
|
||||
CJKReadingSpeed int `json:"cjk_reading_speed"`
|
||||
DefaultHomePage string `json:"default_home_page"`
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password,omitempty"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
Timezone string `json:"timezone"`
|
||||
EntryDirection string `json:"entry_sorting_direction"`
|
||||
EntryOrder string `json:"entry_sorting_order"`
|
||||
Stylesheet string `json:"stylesheet"`
|
||||
GoogleID string `json:"google_id"`
|
||||
OpenIDConnectID string `json:"openid_connect_id"`
|
||||
EntriesPerPage int `json:"entries_per_page"`
|
||||
KeyboardShortcuts bool `json:"keyboard_shortcuts"`
|
||||
ShowReadingTime bool `json:"show_reading_time"`
|
||||
EntrySwipe bool `json:"entry_swipe"`
|
||||
GestureNav string `json:"gesture_nav"`
|
||||
LastLoginAt *time.Time `json:"last_login_at"`
|
||||
DisplayMode string `json:"display_mode"`
|
||||
DefaultReadingSpeed int `json:"default_reading_speed"`
|
||||
CJKReadingSpeed int `json:"cjk_reading_speed"`
|
||||
DefaultHomePage string `json:"default_home_page"`
|
||||
CategoriesSortingOrder string `json:"categories_sorting_order"`
|
||||
MarkReadOnView bool `json:"mark_read_on_view"`
|
||||
MediaPlaybackRate float64 `json:"media_playback_rate"`
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
||||
|
@ -56,25 +59,29 @@ type UserCreationRequest struct {
|
|||
|
||||
// UserModificationRequest represents the request to update a user.
|
||||
type UserModificationRequest struct {
|
||||
Username *string `json:"username"`
|
||||
Password *string `json:"password"`
|
||||
IsAdmin *bool `json:"is_admin"`
|
||||
Theme *string `json:"theme"`
|
||||
Language *string `json:"language"`
|
||||
Timezone *string `json:"timezone"`
|
||||
EntryDirection *string `json:"entry_sorting_direction"`
|
||||
EntryOrder *string `json:"entry_sorting_order"`
|
||||
Stylesheet *string `json:"stylesheet"`
|
||||
GoogleID *string `json:"google_id"`
|
||||
OpenIDConnectID *string `json:"openid_connect_id"`
|
||||
EntriesPerPage *int `json:"entries_per_page"`
|
||||
KeyboardShortcuts *bool `json:"keyboard_shortcuts"`
|
||||
ShowReadingTime *bool `json:"show_reading_time"`
|
||||
EntrySwipe *bool `json:"entry_swipe"`
|
||||
DisplayMode *string `json:"display_mode"`
|
||||
DefaultReadingSpeed *int `json:"default_reading_speed"`
|
||||
CJKReadingSpeed *int `json:"cjk_reading_speed"`
|
||||
DefaultHomePage *string `json:"default_home_page"`
|
||||
Username *string `json:"username"`
|
||||
Password *string `json:"password"`
|
||||
IsAdmin *bool `json:"is_admin"`
|
||||
Theme *string `json:"theme"`
|
||||
Language *string `json:"language"`
|
||||
Timezone *string `json:"timezone"`
|
||||
EntryDirection *string `json:"entry_sorting_direction"`
|
||||
EntryOrder *string `json:"entry_sorting_order"`
|
||||
Stylesheet *string `json:"stylesheet"`
|
||||
GoogleID *string `json:"google_id"`
|
||||
OpenIDConnectID *string `json:"openid_connect_id"`
|
||||
EntriesPerPage *int `json:"entries_per_page"`
|
||||
KeyboardShortcuts *bool `json:"keyboard_shortcuts"`
|
||||
ShowReadingTime *bool `json:"show_reading_time"`
|
||||
EntrySwipe *bool `json:"entry_swipe"`
|
||||
GestureNav *string `json:"gesture_nav"`
|
||||
DisplayMode *string `json:"display_mode"`
|
||||
DefaultReadingSpeed *int `json:"default_reading_speed"`
|
||||
CJKReadingSpeed *int `json:"cjk_reading_speed"`
|
||||
DefaultHomePage *string `json:"default_home_page"`
|
||||
CategoriesSortingOrder *string `json:"categories_sorting_order"`
|
||||
MarkReadOnView *bool `json:"mark_read_on_view"`
|
||||
MediaPlaybackRate *float64 `json:"media_playback_rate"`
|
||||
}
|
||||
|
||||
// Users represents a list of users.
|
||||
|
@ -102,7 +109,7 @@ type Subscription struct {
|
|||
}
|
||||
|
||||
func (s Subscription) String() string {
|
||||
return fmt.Sprintf(`Title="%s", URL="%s", Type="%s"`, s.Title, s.URL, s.Type)
|
||||
return fmt.Sprintf(`Title=%q, URL=%q, Type=%q`, s.Title, s.URL, s.Type)
|
||||
}
|
||||
|
||||
// Subscriptions represents a list of subscriptions.
|
||||
|
@ -135,6 +142,7 @@ type Feed struct {
|
|||
Password string `json:"password"`
|
||||
Category *Category `json:"category,omitempty"`
|
||||
HideGlobally bool `json:"hide_globally"`
|
||||
DisableHTTP2 bool `json:"disable_http2"`
|
||||
}
|
||||
|
||||
// FeedCreationRequest represents the request to create a feed.
|
||||
|
@ -155,6 +163,7 @@ type FeedCreationRequest struct {
|
|||
BlocklistRules string `json:"blocklist_rules"`
|
||||
KeeplistRules string `json:"keeplist_rules"`
|
||||
HideGlobally bool `json:"hide_globally"`
|
||||
DisableHTTP2 bool `json:"disable_http2"`
|
||||
}
|
||||
|
||||
// FeedModificationRequest represents the request to update a feed.
|
||||
|
@ -177,6 +186,7 @@ type FeedModificationRequest struct {
|
|||
AllowSelfSignedCertificates *bool `json:"allow_self_signed_certificates"`
|
||||
FetchViaProxy *bool `json:"fetch_via_proxy"`
|
||||
HideGlobally *bool `json:"hide_globally"`
|
||||
DisableHTTP2 *bool `json:"disable_http2"`
|
||||
}
|
||||
|
||||
// FeedIcon represents the feed icon.
|
||||
|
@ -197,23 +207,30 @@ type Feeds []*Feed
|
|||
// Entry represents a subscription item in the system.
|
||||
type Entry struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
FeedID int64 `json:"feed_id"`
|
||||
Status string `json:"status"`
|
||||
Date time.Time `json:"published_at"`
|
||||
ChangedAt time.Time `json:"changed_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Feed *Feed `json:"feed,omitempty"`
|
||||
Hash string `json:"hash"`
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
CommentsURL string `json:"comments_url"`
|
||||
Date time.Time `json:"published_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ChangedAt time.Time `json:"changed_at"`
|
||||
Title string `json:"title"`
|
||||
Status string `json:"status"`
|
||||
Content string `json:"content"`
|
||||
Author string `json:"author"`
|
||||
ShareCode string `json:"share_code"`
|
||||
Starred bool `json:"starred"`
|
||||
ReadingTime int `json:"reading_time"`
|
||||
Enclosures Enclosures `json:"enclosures,omitempty"`
|
||||
Feed *Feed `json:"feed,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
ReadingTime int `json:"reading_time"`
|
||||
UserID int64 `json:"user_id"`
|
||||
FeedID int64 `json:"feed_id"`
|
||||
Starred bool `json:"starred"`
|
||||
}
|
||||
|
||||
// EntryModificationRequest represents a request to modify an entry.
|
||||
type EntryModificationRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
}
|
||||
|
||||
// Entries represents a list of entries.
|
||||
|
@ -239,20 +256,24 @@ const (
|
|||
|
||||
// Filter is used to filter entries.
|
||||
type Filter struct {
|
||||
Status string
|
||||
Offset int
|
||||
Limit int
|
||||
Order string
|
||||
Direction string
|
||||
Starred string
|
||||
Before int64
|
||||
After int64
|
||||
BeforeEntryID int64
|
||||
AfterEntryID int64
|
||||
Search string
|
||||
CategoryID int64
|
||||
FeedID int64
|
||||
Statuses []string
|
||||
Status string
|
||||
Offset int
|
||||
Limit int
|
||||
Order string
|
||||
Direction string
|
||||
Starred string
|
||||
Before int64
|
||||
After int64
|
||||
PublishedBefore int64
|
||||
PublishedAfter int64
|
||||
ChangedBefore int64
|
||||
ChangedAfter int64
|
||||
BeforeEntryID int64
|
||||
AfterEntryID int64
|
||||
Search string
|
||||
CategoryID int64
|
||||
FeedID int64
|
||||
Statuses []string
|
||||
}
|
||||
|
||||
// EntryResultSet represents the response when fetching entries.
|
||||
|
@ -260,3 +281,18 @@ type EntryResultSet struct {
|
|||
Total int `json:"total"`
|
||||
Entries Entries `json:"entries"`
|
||||
}
|
||||
|
||||
// VersionResponse represents the version and the build information of the Miniflux instance.
|
||||
type VersionResponse struct {
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
BuildDate string `json:"build_date"`
|
||||
GoVersion string `json:"go_version"`
|
||||
Compiler string `json:"compiler"`
|
||||
Arch string `json:"arch"`
|
||||
OS string `json:"os"`
|
||||
}
|
||||
|
||||
func SetOptionalField[T any](value T) *T {
|
||||
return &value
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package client // import "miniflux.app/client"
|
||||
package client // import "miniflux.app/v2/client"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -27,6 +26,7 @@ var (
|
|||
ErrForbidden = errors.New("miniflux: access forbidden")
|
||||
ErrServerError = errors.New("miniflux: internal server error")
|
||||
ErrNotFound = errors.New("miniflux: resource not found")
|
||||
ErrBadRequest = errors.New("miniflux: bad request")
|
||||
)
|
||||
|
||||
type errorResponse struct {
|
||||
|
@ -125,10 +125,10 @@ func (r *request) execute(method, path string, data interface{}) (io.ReadCloser,
|
|||
var resp errorResponse
|
||||
decoder := json.NewDecoder(response.Body)
|
||||
if err := decoder.Decode(&resp); err != nil {
|
||||
return nil, fmt.Errorf("miniflux: bad request error (%v)", err)
|
||||
return nil, fmt.Errorf("%w (%v)", ErrBadRequest, err)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("miniflux: bad request (%s)", resp.ErrorMessage)
|
||||
return nil, fmt.Errorf("%w (%s)", ErrBadRequest, resp.ErrorMessage)
|
||||
}
|
||||
|
||||
if response.StatusCode > 400 {
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package config // import "miniflux.app/config"
|
||||
|
||||
// Opts holds parsed configuration options.
|
||||
var Opts *Options
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2019 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package config handles configuration management for the application.
|
||||
*/
|
||||
package config // import "miniflux.app/config"
|
|
@ -0,0 +1,6 @@
|
|||
This folder contains Miniflux API collection for [Bruno](https://www.usebruno.com).
|
||||
|
||||
Bruno is a lightweight alternative to Postman/Insomnia.
|
||||
|
||||
- https://www.usebruno.com
|
||||
- https://github.com/usebruno/bruno
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Bookmark an entry
|
||||
type: http
|
||||
seq: 37
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/entries/{{entryID}}/bookmark
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
entryID: 1698
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Create a feed
|
||||
type: http
|
||||
seq: 19
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/feeds
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Create a new category
|
||||
type: http
|
||||
seq: 10
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/categories
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
meta {
|
||||
name: Create a new user
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/users
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"username": "foobar",
|
||||
"password": "secret123"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Delete a category
|
||||
type: http
|
||||
seq: 12
|
||||
}
|
||||
|
||||
delete {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 1
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Delete a feed
|
||||
type: http
|
||||
seq: 26
|
||||
}
|
||||
|
||||
delete {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 18
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Delete a user
|
||||
type: http
|
||||
seq: 7
|
||||
}
|
||||
|
||||
delete {
|
||||
url: {{minifluxBaseURL}}/v1/users/{{userID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"language": "fr_FR"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
userID: 2
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Discover feeds
|
||||
type: http
|
||||
seq: 18
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/discover
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"url": "https://miniflux.app"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Fetch entry website content
|
||||
type: http
|
||||
seq: 39
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/entries/{{entryID}}/fetch-content
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
entryID: 1698
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Flush history
|
||||
type: http
|
||||
seq: 40
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/flush-history
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"url": "https://miniflux.app"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get a single entry
|
||||
type: http
|
||||
seq: 36
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/entries/{{entryID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
entryID: 1698
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
meta {
|
||||
name: Get a single feed entry
|
||||
type: http
|
||||
seq: 33
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}/entries/{{entryID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
entryID: 1698
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get a single feed
|
||||
type: http
|
||||
seq: 24
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 18
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
meta {
|
||||
name: Get a single user by ID
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/users/{{userID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
userID: 1
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
meta {
|
||||
name: Get a single user by username
|
||||
type: http
|
||||
seq: 4
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/users/{{username}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
username: admin
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
meta {
|
||||
name: Get all categories
|
||||
type: http
|
||||
seq: 9
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/categories
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Get all entries
|
||||
type: http
|
||||
seq: 34
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/entries
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Get all feeds
|
||||
type: http
|
||||
seq: 20
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
meta {
|
||||
name: Get all users
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/users
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get category entries
|
||||
type: http
|
||||
seq: 16
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}/entries
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 2
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
meta {
|
||||
name: Get category entry
|
||||
type: http
|
||||
seq: 17
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}/entries/{{entryID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 2
|
||||
entryID: 1
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get category feeds
|
||||
type: http
|
||||
seq: 14
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}/feeds
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 2
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
meta {
|
||||
name: Get current user
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/me
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Get feed counters
|
||||
type: http
|
||||
seq: 21
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/counters
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get feed entries
|
||||
type: http
|
||||
seq: 32
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}/entries
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get feed icon by feed ID
|
||||
type: http
|
||||
seq: 27
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}/icon
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Get feed icon by icon ID
|
||||
type: http
|
||||
seq: 28
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/icons/{{iconID}}
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
iconID: 11
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
meta {
|
||||
name: Get version and build information
|
||||
type: http
|
||||
seq: 42
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/version
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Mark all category entries as read
|
||||
type: http
|
||||
seq: 13
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}/mark-all-as-read
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 2
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Mark all user entries as read
|
||||
type: http
|
||||
seq: 8
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/users/{{userID}}/mark-all-as-read
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
userID: 1
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Mark feed as read
|
||||
type: http
|
||||
seq: 29
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}/mark-all-as-read
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: OPML Export
|
||||
type: http
|
||||
seq: 30
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{minifluxBaseURL}}/v1/export
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
meta {
|
||||
name: OPML Import
|
||||
type: http
|
||||
seq: 31
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/import
|
||||
body: xml
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
body:xml {
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<opml version="2.0">
|
||||
<head>
|
||||
<title>Miniflux</title>
|
||||
</head>
|
||||
<body>
|
||||
<outline text="My category">
|
||||
<outline title="Miniflux" text="Miniflux" xmlUrl="https://miniflux.app/feed.xml" htmlUrl="https://miniflux.app"></outline>
|
||||
</outline>
|
||||
</body>
|
||||
</opml>
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 19
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Refresh a single feed
|
||||
type: http
|
||||
seq: 23
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}/refresh
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 18
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
meta {
|
||||
name: Refresh all feeds
|
||||
type: http
|
||||
seq: 22
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/refresh
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Refresh category feeds
|
||||
type: http
|
||||
seq: 15
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}/refresh
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 2
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Save an entry
|
||||
type: http
|
||||
seq: 38
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{minifluxBaseURL}}/v1/entries/{{entryID}}/save
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"feed_url": "https://miniflux.app/feed.xml"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
entryID: 1698
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Update a category
|
||||
type: http
|
||||
seq: 11
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/categories/{{categoryID}}
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "Test Update"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
categoryID: 1
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Update a feed
|
||||
type: http
|
||||
seq: 25
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/feeds/{{feedID}}
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"user_agent": "My user agent"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
feedID: 18
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
meta {
|
||||
name: Update a user
|
||||
type: http
|
||||
seq: 6
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/users/{{userID}}
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"language": "fr_FR"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
userID: 1
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
meta {
|
||||
name: Update entries status
|
||||
type: http
|
||||
seq: 35
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/entries
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"entry_ids": [1698, 1699],
|
||||
"status": "read"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
meta {
|
||||
name: Update entry
|
||||
type: http
|
||||
seq: 41
|
||||
}
|
||||
|
||||
put {
|
||||
url: {{minifluxBaseURL}}/v1/entries/{{entryID}}
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: {{minifluxUsername}}
|
||||
password: {{minifluxPassword}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"title": "New title",
|
||||
"content": "Some text"
|
||||
}
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
entryID: 1789
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"version": "1",
|
||||
"name": "Miniflux",
|
||||
"type": "collection"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
vars {
|
||||
minifluxBaseURL: http://127.0.0.1:8080
|
||||
minifluxUsername: admin
|
||||
}
|
||||
vars:secret [
|
||||
minifluxPassword
|
||||
]
|
|
@ -8,6 +8,5 @@ Here are few Docker Compose examples:
|
|||
- `traefik.yml`: Use Traefik as reverse-proxy with automatic HTTPS
|
||||
|
||||
```bash
|
||||
docker-compose -f basic.yml up -d db
|
||||
docker-compose -f basic.yml up
|
||||
docker compose -f basic.yml up -d
|
||||
```
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3.4'
|
||||
services:
|
||||
miniflux:
|
||||
image: ${MINIFLUX_IMAGE:-miniflux/miniflux:latest}
|
||||
|
@ -7,7 +6,8 @@ services:
|
|||
ports:
|
||||
- "80:8080"
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
|
||||
- RUN_MIGRATIONS=1
|
||||
|
@ -19,11 +19,12 @@ services:
|
|||
# healthcheck:
|
||||
# test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
|
||||
db:
|
||||
image: postgres:latest
|
||||
image: postgres:15
|
||||
container_name: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=miniflux
|
||||
- POSTGRES_PASSWORD=secret
|
||||
- POSTGRES_DB=miniflux
|
||||
volumes:
|
||||
- miniflux-db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3.4'
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2
|
||||
|
@ -16,7 +15,8 @@ services:
|
|||
image: ${MINIFLUX_IMAGE:-miniflux/miniflux:latest}
|
||||
container_name: miniflux
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
|
||||
- RUN_MIGRATIONS=1
|
||||
|
@ -25,7 +25,7 @@ services:
|
|||
- ADMIN_PASSWORD=test123
|
||||
- BASE_URL=https://miniflux.example.org
|
||||
db:
|
||||
image: postgres:latest
|
||||
image: postgres:15
|
||||
container_name: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=miniflux
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3.4'
|
||||
services:
|
||||
traefik:
|
||||
image: "traefik:v2.3"
|
||||
|
@ -21,7 +20,8 @@ services:
|
|||
image: ${MINIFLUX_IMAGE:-miniflux/miniflux:latest}
|
||||
container_name: miniflux
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
condition: service_healthy
|
||||
expose:
|
||||
- "8080"
|
||||
environment:
|
||||
|
@ -37,7 +37,7 @@ services:
|
|||
- "traefik.http.routers.miniflux.entrypoints=websecure"
|
||||
- "traefik.http.routers.miniflux.tls.certresolver=myresolver"
|
||||
db:
|
||||
image: postgres:latest
|
||||
image: postgres:15
|
||||
container_name: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=miniflux
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
|
@ -104,7 +104,7 @@
|
|||
"type": "bargauge"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
|
@ -289,7 +289,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
|
@ -332,7 +332,7 @@
|
|||
"pluginVersion": "7.1.5",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_sys_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_sys_bytes{job=\"miniflux\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "{{ instance }} - Memory Used",
|
||||
"refId": "A"
|
||||
|
@ -348,7 +348,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
|
@ -440,7 +440,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
|
@ -529,7 +529,7 @@
|
|||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
|
@ -546,7 +546,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
|
@ -590,7 +590,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_sys_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_sys_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -699,7 +699,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "process_open_fds{app=\"miniflux\"}",
|
||||
"expr": "process_open_fds{job=\"miniflux\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "{{instance }} - Open File Descriptors",
|
||||
"refId": "A"
|
||||
|
@ -748,7 +748,7 @@
|
|||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
|
@ -816,7 +816,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_alloc_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_alloc_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
|
@ -826,7 +826,7 @@
|
|||
"step": 4
|
||||
},
|
||||
{
|
||||
"expr": "rate(go_memstats_alloc_bytes_total{app=\"miniflux\"}[30s])",
|
||||
"expr": "rate(go_memstats_alloc_bytes_total{job=\"miniflux\"}[30s])",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
|
@ -836,7 +836,7 @@
|
|||
"step": 4
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_stack_inuse_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_stack_inuse_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
|
@ -846,7 +846,7 @@
|
|||
"step": 4
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_heap_inuse_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_inuse_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"interval": "",
|
||||
|
@ -904,7 +904,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
|
@ -945,13 +945,13 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_goroutines{app=\"miniflux\"}",
|
||||
"expr": "go_goroutines{job=\"miniflux\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "{{ instance }} - Goroutines",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "go_threads{app=\"miniflux\"}",
|
||||
"expr": "go_threads{job=\"miniflux\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "{{ instance }} - OS threads",
|
||||
"refId": "B"
|
||||
|
@ -1003,7 +1003,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
|
@ -1046,7 +1046,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_stack_inuse_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_stack_inuse_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1054,7 +1054,7 @@
|
|||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_stack_sys_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_stack_sys_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1108,7 +1108,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
|
@ -1150,7 +1150,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_heap_alloc_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_alloc_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1158,7 +1158,7 @@
|
|||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_heap_sys_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_sys_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1166,7 +1166,7 @@
|
|||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_heap_idle_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_idle_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1174,7 +1174,7 @@
|
|||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_heap_inuse_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_inuse_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1182,7 +1182,7 @@
|
|||
"refId": "D"
|
||||
},
|
||||
{
|
||||
"expr": "go_memstats_heap_released_bytes{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_heap_released_bytes{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1282,7 +1282,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_gc_duration_seconds{app=\"miniflux\"}",
|
||||
"expr": "go_gc_duration_seconds{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 2,
|
||||
|
@ -1339,7 +1339,7 @@
|
|||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"datasource": "Prometheus",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {},
|
||||
|
@ -1383,7 +1383,7 @@
|
|||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "go_memstats_mallocs_total{app=\"miniflux\"} - go_memstats_frees_total{app=\"miniflux\"}",
|
||||
"expr": "go_memstats_mallocs_total{job=\"miniflux\"} - go_memstats_frees_total{job=\"miniflux\"}",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
|
@ -1462,4 +1462,4 @@
|
|||
"title": "Miniflux",
|
||||
"uid": "vSaPgcFMk",
|
||||
"version": 23
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Miniflux API Collection for Thunder Client VS Code Extension
|
||||
============================================================
|
||||
|
||||
Official website: https://www.thunderclient.com
|
||||
|
||||
This folder contains the API endpoints collection for Miniflux. You can import it locally to interact with the Miniflux API.
|
|
@ -0,0 +1,769 @@
|
|||
{
|
||||
"client": "Thunder Client",
|
||||
"collectionName": "Miniflux v2",
|
||||
"dateExported": "2023-07-31T01:53:38.743Z",
|
||||
"version": "1.1",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"_id": "d23fb9ba-c0c1-46ff-93f4-c5ed24ecd56e",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Discover Subscriptions",
|
||||
"url": "/v1/discover",
|
||||
"method": "POST",
|
||||
"sortNum": 20000,
|
||||
"created": "2023-07-31T01:20:12.275Z",
|
||||
"modified": "2023-07-31T01:29:39.751Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "\n{\n \"url\": \"https://miniflux.app/\"\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "29cfc679-31d4-4d8c-b843-ab92a74dfa85",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Feeds",
|
||||
"url": "/v1/feeds",
|
||||
"method": "GET",
|
||||
"sortNum": 50000,
|
||||
"created": "2023-07-31T01:20:12.276Z",
|
||||
"modified": "2023-07-31T01:20:12.276Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "52a88df8-41c7-47c2-a635-8c93d7d29f40",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Category Feeds",
|
||||
"url": "/v1/categories/1/feeds",
|
||||
"method": "GET",
|
||||
"sortNum": 60000,
|
||||
"created": "2023-07-31T01:20:12.277Z",
|
||||
"modified": "2023-07-31T01:20:12.277Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "a5c2cb48-a4cf-4edc-a0e0-927d9f711843",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Feed",
|
||||
"url": "/v1/feeds/{feedID}",
|
||||
"method": "GET",
|
||||
"sortNum": 70000,
|
||||
"created": "2023-07-31T01:20:12.279Z",
|
||||
"modified": "2023-07-31T01:31:11.478Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "fb55b058-c2ba-4785-be92-a98f0596e86e",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Feed Icon ",
|
||||
"url": "/v1/feeds/{feedID}/icon",
|
||||
"method": "GET",
|
||||
"sortNum": 80000,
|
||||
"created": "2023-07-31T01:20:12.280Z",
|
||||
"modified": "2023-07-31T01:31:18.174Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "c0ec9a45-263e-4627-a13b-b5df901a6456",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Create Feed ",
|
||||
"url": "/v1/feeds",
|
||||
"method": "POST",
|
||||
"sortNum": 90000,
|
||||
"created": "2023-07-31T01:20:12.281Z",
|
||||
"modified": "2023-07-31T01:31:31.415Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"feed_url\": \"https://miniflux.app/feed.xml\",\n \"category_id\": 1\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "f4c078a2-c031-4753-a7a4-4987439a61d0",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Update Feed",
|
||||
"url": "/v1/feeds/{feedID}",
|
||||
"method": "PUT",
|
||||
"sortNum": 100000,
|
||||
"created": "2023-07-31T01:20:12.282Z",
|
||||
"modified": "2023-07-31T01:31:48.115Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"title\": \"Updated - New Feed Title\",\n \"category_id\": 1\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "1e47aeab-09ce-439b-907f-f9347b98b160",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Refresh Feed",
|
||||
"url": "/v1/feeds/{feedID}/refresh",
|
||||
"method": "PUT",
|
||||
"sortNum": 110000,
|
||||
"created": "2023-07-31T01:20:12.283Z",
|
||||
"modified": "2023-07-31T01:31:58.778Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "4f643fa6-042d-4e95-8194-4cb0af7102bf",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Refresh All Feeds",
|
||||
"url": "/v1/feeds/refresh",
|
||||
"method": "PUT",
|
||||
"sortNum": 115000,
|
||||
"created": "2023-07-31T01:20:12.312Z",
|
||||
"modified": "2023-07-31T01:20:12.312Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "d829f651-e9b9-41f9-aa9e-bd830d5e6389",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Remove Feed",
|
||||
"url": "/v1/feeds/{feedID}",
|
||||
"method": "DELETE",
|
||||
"sortNum": 120000,
|
||||
"created": "2023-07-31T01:20:12.284Z",
|
||||
"modified": "2023-07-31T01:32:16.723Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "deafbf1a-d9e0-420f-a749-1bdde56772cb",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Feed Entries",
|
||||
"url": "/v1/feeds/{feedID}/entries",
|
||||
"method": "GET",
|
||||
"sortNum": 130000,
|
||||
"created": "2023-07-31T01:20:12.285Z",
|
||||
"modified": "2023-07-31T01:32:52.812Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "2",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "0052e903-75fc-48ec-8fd5-6e8784ed401a",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Entry",
|
||||
"url": "/v1/entries/{entryID}",
|
||||
"method": "GET",
|
||||
"sortNum": 140000,
|
||||
"created": "2023-07-31T01:20:12.286Z",
|
||||
"modified": "2023-07-31T01:33:30.417Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "entryID",
|
||||
"value": "19",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "1a055ace-2629-4298-9ea0-1bd17d59a4d6",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Fetch original article",
|
||||
"url": "/v1/entries/{entryID}/fetch-content",
|
||||
"method": "GET",
|
||||
"sortNum": 150000,
|
||||
"created": "2023-07-31T01:20:12.287Z",
|
||||
"modified": "2023-07-31T01:33:41.014Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "entryID",
|
||||
"value": "19",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "f272d1e6-ebbb-4c58-a159-4412ad657136",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Category Entries",
|
||||
"url": "/v1/categories/{categoryID}/entries",
|
||||
"method": "GET",
|
||||
"sortNum": 160000,
|
||||
"created": "2023-07-31T01:20:12.288Z",
|
||||
"modified": "2023-07-31T01:20:12.288Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "856ed091-318a-4a76-b7ce-6475106dd6b5",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Mark All Feed Entries as Read",
|
||||
"url": "/v1/feeds/{feedID}/mark-all-as-read",
|
||||
"method": "PUT",
|
||||
"sortNum": 180000,
|
||||
"created": "2023-07-31T01:20:12.290Z",
|
||||
"modified": "2023-07-31T01:46:57.443Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "feedID",
|
||||
"value": "2",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "67749962-d646-45d5-8b78-a8eeaa7cb971",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Entries",
|
||||
"url": "/v1/entries",
|
||||
"method": "GET",
|
||||
"sortNum": 190000,
|
||||
"created": "2023-07-31T01:20:12.291Z",
|
||||
"modified": "2023-07-31T01:20:12.291Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "b55ae165-2abe-41f0-8b8a-14d826238d20",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Change Entries Status",
|
||||
"url": "/v1/entries",
|
||||
"method": "PUT",
|
||||
"sortNum": 200000,
|
||||
"created": "2023-07-31T01:20:12.292Z",
|
||||
"modified": "2023-07-31T01:46:46.133Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"entry_ids\": [19, 20],\n \"status\": \"read\"\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "710dfc55-fc4e-48ab-989e-3ed78019d6c3",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Toggle Entry Bookmark",
|
||||
"url": "/v1/entries/{entryID}/bookmark",
|
||||
"method": "PUT",
|
||||
"sortNum": 210000,
|
||||
"created": "2023-07-31T01:20:12.293Z",
|
||||
"modified": "2023-07-31T01:45:51.933Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "entryID",
|
||||
"value": "19",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "19edbe55-0a0a-4102-bde0-73ed6d8515f6",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Save Entry to Third-Party Service",
|
||||
"url": "/v1/entries/{entryID}/save",
|
||||
"method": "POST",
|
||||
"sortNum": 215000,
|
||||
"created": "2023-07-31T01:20:12.313Z",
|
||||
"modified": "2023-07-31T01:20:12.313Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "entryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "13d2cf52-aa08-4f7f-a83d-ffcb1e1190cd",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Categories",
|
||||
"url": "/v1/categories",
|
||||
"method": "GET",
|
||||
"sortNum": 220000,
|
||||
"created": "2023-07-31T01:20:12.294Z",
|
||||
"modified": "2023-07-31T01:20:12.294Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "1547dabe-2bcb-4e06-acaa-fb393d1027e2",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Create Category ",
|
||||
"url": "/v1/categories",
|
||||
"method": "POST",
|
||||
"sortNum": 230000,
|
||||
"created": "2023-07-31T01:20:12.295Z",
|
||||
"modified": "2023-07-31T01:20:12.295Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"title\": \"My category\"\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "e8dac503-19dc-434d-832f-eac4364785d8",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Update Category",
|
||||
"url": "/v1/categories/{categoryID}",
|
||||
"method": "PUT",
|
||||
"sortNum": 232500,
|
||||
"created": "2023-07-31T01:20:12.296Z",
|
||||
"modified": "2023-07-31T01:42:55.831Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "3",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "\n{\n \"title\": \"My new title\"\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "86d74247-7f12-4a6e-91b3-fad9e7b6b1fb",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Delete Category",
|
||||
"url": "/v1/categories/{categoryID}",
|
||||
"method": "DELETE",
|
||||
"sortNum": 235000,
|
||||
"created": "2023-07-31T01:20:12.298Z",
|
||||
"modified": "2023-07-31T01:44:21.486Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "3",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "668dde80-ed03-4fa6-ad2a-9cacd0ec31eb",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Mark Category Entries as Read",
|
||||
"url": "/v1/categories/{categoryID}/mark-all-as-read",
|
||||
"method": "PUT",
|
||||
"sortNum": 237500,
|
||||
"created": "2023-07-31T01:20:12.299Z",
|
||||
"modified": "2023-07-31T01:43:50.637Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "39ada469-765e-4584-ab00-9d263bd526a1",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Category Feeds",
|
||||
"url": "/v1/categories/{categoryID}/feeds",
|
||||
"method": "GET",
|
||||
"sortNum": 243750,
|
||||
"created": "2023-07-31T01:50:23.959Z",
|
||||
"modified": "2023-07-31T01:50:51.443Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "ec389c41-185f-4b57-a373-c6ff952b4282",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Refresh Category Feeds",
|
||||
"url": "/v1/categories/{categoryID}/refresh",
|
||||
"method": "PUT",
|
||||
"sortNum": 250000,
|
||||
"created": "2023-07-31T01:20:12.297Z",
|
||||
"modified": "2023-07-31T01:43:23.102Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "bc4a7578-c95e-4436-bbfa-61ccc4a8fc71",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Category Entries",
|
||||
"url": "/v1/categories/{categoryID}/entries",
|
||||
"method": "GET",
|
||||
"sortNum": 257500,
|
||||
"created": "2023-07-31T01:51:15.403Z",
|
||||
"modified": "2023-07-31T01:51:35.106Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "fa935fb3-3ed6-4ee3-b995-6c054766d109",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Category Entry",
|
||||
"url": "/v1/categories/{categoryID}/entries/{entryID}",
|
||||
"method": "GET",
|
||||
"sortNum": 258750,
|
||||
"created": "2023-07-31T01:51:46.699Z",
|
||||
"modified": "2023-07-31T01:52:12.155Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "categoryID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
},
|
||||
{
|
||||
"name": "entryID",
|
||||
"value": "19",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "cb6968e9-8d13-4410-9ad5-85847b73d7eb",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "OPML Export",
|
||||
"url": "/v1/export",
|
||||
"method": "GET",
|
||||
"sortNum": 280000,
|
||||
"created": "2023-07-31T01:20:12.300Z",
|
||||
"modified": "2023-07-31T01:20:12.300Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "169a64e1-08dd-4760-b405-a748a5286b38",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "OPML Import",
|
||||
"url": "/v1/import",
|
||||
"method": "POST",
|
||||
"sortNum": 290000,
|
||||
"created": "2023-07-31T01:20:12.301Z",
|
||||
"modified": "2023-07-31T01:41:31.218Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "xml",
|
||||
"raw": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<opml version=\"2.0\">\n <head>\n <title>Miniflux</title>\n <dateCreated>Sun, 30 Jul 2023 18:41:08 PDT</dateCreated>\n </head>\n <body>\n <outline text=\"All\">\n <outline title=\"Miniflux\" text=\"Miniflux\" xmlUrl=\"https://miniflux.app/feed.xml\" htmlUrl=\"https://miniflux.app\"></outline>\n </outline>\n </body>\n</opml>",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "bfb7264a-7b46-49fe-b451-fb6d9b03f0b2",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Create User",
|
||||
"url": "/v1/users",
|
||||
"method": "POST",
|
||||
"sortNum": 300000,
|
||||
"created": "2023-07-31T01:20:12.302Z",
|
||||
"modified": "2023-07-31T01:20:12.302Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"username\": \"bob\",\n \"password\": \"test123\",\n \"is_admin\": false\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "93c1dcc2-bf09-4e8e-86ba-0c042147a48f",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Update User",
|
||||
"url": "/v1/users/{userID}",
|
||||
"method": "PUT",
|
||||
"sortNum": 310000,
|
||||
"created": "2023-07-31T01:20:12.303Z",
|
||||
"modified": "2023-07-31T01:40:09.576Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "userID",
|
||||
"value": "2",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"username\": \"joe\"\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "19cf34c1-eb0a-4442-a682-2e94c4f5e594",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Current User",
|
||||
"url": "/v1/me",
|
||||
"method": "GET",
|
||||
"sortNum": 320000,
|
||||
"created": "2023-07-31T01:20:12.304Z",
|
||||
"modified": "2023-07-31T01:20:12.304Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "4a700f7c-8762-4cab-aab1-2d8066884d69",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get User by ID",
|
||||
"url": "/v1/users/{userID}",
|
||||
"method": "GET",
|
||||
"sortNum": 330000,
|
||||
"created": "2023-07-31T01:20:12.305Z",
|
||||
"modified": "2023-07-31T01:39:38.472Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "userID",
|
||||
"value": "1",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "66cb0985-5ed4-4b1e-9029-8605b7f5f74e",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get User by username",
|
||||
"url": "/v1/users/{username}",
|
||||
"method": "GET",
|
||||
"sortNum": 335000,
|
||||
"created": "2023-07-31T01:47:53.649Z",
|
||||
"modified": "2023-07-31T01:48:10.655Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "username",
|
||||
"value": "admin",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "3d4b227a-83a2-4d87-a0ed-ce9d5497aea6",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Get Users",
|
||||
"url": "/v1/users",
|
||||
"method": "GET",
|
||||
"sortNum": 340000,
|
||||
"created": "2023-07-31T01:20:12.306Z",
|
||||
"modified": "2023-07-31T01:20:12.306Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "90138dea-799a-4b44-ad68-fce6ec5898a6",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Delete User",
|
||||
"url": "/v1/users/{userID}",
|
||||
"method": "DELETE",
|
||||
"sortNum": 350000,
|
||||
"created": "2023-07-31T01:20:12.307Z",
|
||||
"modified": "2023-07-31T01:40:38.124Z",
|
||||
"headers": [],
|
||||
"params": [
|
||||
{
|
||||
"name": "userID",
|
||||
"value": "2",
|
||||
"isPath": true
|
||||
}
|
||||
],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "4b3bf7ca-bc55-423b-a3ee-6279c10a0d85",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Fetch Read/Unread Counters",
|
||||
"url": "/v1/feeds/counters",
|
||||
"method": "GET",
|
||||
"sortNum": 370000,
|
||||
"created": "2023-07-31T01:20:12.309Z",
|
||||
"modified": "2023-07-31T01:20:12.309Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "7721682f-31e3-4d71-8df9-02e30e4729d7",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Healthcheck",
|
||||
"url": "/healthcheck",
|
||||
"method": "GET",
|
||||
"sortNum": 380000,
|
||||
"created": "2023-07-31T01:20:12.310Z",
|
||||
"modified": "2023-07-31T01:20:12.310Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "64410254-b17a-43e4-984d-10b9b13c5818",
|
||||
"colId": "fc35618a-f39f-40a0-a443-d4ae568baa8e",
|
||||
"containerId": "",
|
||||
"name": "Version",
|
||||
"url": "/version",
|
||||
"method": "GET",
|
||||
"sortNum": 390000,
|
||||
"created": "2023-07-31T01:20:12.311Z",
|
||||
"modified": "2023-07-31T01:20:12.311Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"auth": {
|
||||
"type": "basic",
|
||||
"basic": {
|
||||
"username": "admin",
|
||||
"password": "test123"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseUrl": "http://localhost:8080"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package crypto // import "miniflux.app/crypto"
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// HashFromBytes returns a SHA-256 checksum of the input.
|
||||
func HashFromBytes(value []byte) string {
|
||||
sum := sha256.Sum256(value)
|
||||
return fmt.Sprintf("%x", sum)
|
||||
}
|
||||
|
||||
// Hash returns a SHA-256 checksum of a string.
|
||||
func Hash(value string) string {
|
||||
return HashFromBytes([]byte(value))
|
||||
}
|
||||
|
||||
// GenerateRandomBytes returns random bytes.
|
||||
func GenerateRandomBytes(size int) []byte {
|
||||
b := make([]byte, size)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// GenerateRandomString returns a random string.
|
||||
func GenerateRandomString(size int) string {
|
||||
return base64.URLEncoding.EncodeToString(GenerateRandomBytes(size))
|
||||
}
|
||||
|
||||
// GenerateRandomStringHex returns a random hexadecimal string.
|
||||
func GenerateRandomStringHex(size int) string {
|
||||
return hex.EncodeToString(GenerateRandomBytes(size))
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package crypto implements helpers related to cryptography.
|
||||
*/
|
||||
package crypto // import "miniflux.app/crypto"
|
8
doc.go
8
doc.go
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Miniflux is a feed reader application.
|
||||
*/
|
||||
package main // import "miniflux.app"
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package errors handles localized errors.
|
||||
*/
|
||||
package errors // import "miniflux.app/errors"
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright 2017 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package errors // import "miniflux.app/errors"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"miniflux.app/locale"
|
||||
)
|
||||
|
||||
// LocalizedError represents an error than could be translated to another language.
|
||||
type LocalizedError struct {
|
||||
message string
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
// Error returns untranslated error message.
|
||||
func (l LocalizedError) Error() string {
|
||||
return fmt.Sprintf(l.message, l.args...)
|
||||
}
|
||||
|
||||
// Localize returns the translated error message.
|
||||
func (l LocalizedError) Localize(printer *locale.Printer) string {
|
||||
return printer.Printf(l.message, l.args...)
|
||||
}
|
||||
|
||||
// NewLocalizedError returns a new LocalizedError.
|
||||
func NewLocalizedError(message string, args ...interface{}) *LocalizedError {
|
||||
return &LocalizedError{message: message, args: args}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package fever implements Fever API endpoints.
|
||||
*/
|
||||
package fever // import "miniflux.app/fever"
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fever // import "miniflux.app/fever"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"miniflux.app/http/request"
|
||||
"miniflux.app/http/response/json"
|
||||
"miniflux.app/logger"
|
||||
"miniflux.app/storage"
|
||||
)
|
||||
|
||||
type middleware struct {
|
||||
store *storage.Storage
|
||||
}
|
||||
|
||||
func newMiddleware(s *storage.Storage) *middleware {
|
||||
return &middleware{s}
|
||||
}
|
||||
|
||||
func (m *middleware) serve(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := request.ClientIP(r)
|
||||
apiKey := r.FormValue("api_key")
|
||||
if apiKey == "" {
|
||||
logger.Info("[Fever] [ClientIP=%s] No API key provided", clientIP)
|
||||
json.OK(w, r, newAuthFailureResponse())
|
||||
return
|
||||
}
|
||||
|
||||
user, err := m.store.UserByFeverToken(apiKey)
|
||||
if err != nil {
|
||||
logger.Error("[Fever] %v", err)
|
||||
json.OK(w, r, newAuthFailureResponse())
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
logger.Info("[Fever] [ClientIP=%s] No user found with this API key", clientIP)
|
||||
json.OK(w, r, newAuthFailureResponse())
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("[Fever] [ClientIP=%s] User #%d is authenticated with user agent %q", clientIP, user.ID, r.UserAgent())
|
||||
m.store.SetLastLogin(user.ID)
|
||||
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, request.UserIDContextKey, user.ID)
|
||||
ctx = context.WithValue(ctx, request.UserTimezoneContextKey, user.Timezone)
|
||||
ctx = context.WithValue(ctx, request.IsAdminUserContextKey, user.IsAdmin)
|
||||
ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)
|
||||
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
66
go.mod
66
go.mod
|
@ -1,29 +1,47 @@
|
|||
module miniflux.app
|
||||
module miniflux.app/v2
|
||||
|
||||
// +heroku goVersion go1.16
|
||||
// +heroku goVersion go1.22
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/lib/pq v1.10.7
|
||||
github.com/mitchellh/go-server-timing v1.0.2-0.20201108055052-feb680ab92c2
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/rylans/getlang v0.0.0-20200505200108-4c3188ff8a2d
|
||||
github.com/tdewolff/minify/v2 v2.12.4
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||
github.com/yuin/goldmark v1.5.2
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
mvdan.cc/xurls/v2 v2.4.0
|
||||
github.com/PuerkitoBio/goquery v1.9.2
|
||||
github.com/abadojack/whatlanggo v1.0.1
|
||||
github.com/andybalholm/brotli v1.1.0
|
||||
github.com/coreos/go-oidc/v3 v3.10.0
|
||||
github.com/go-webauthn/webauthn v0.10.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/tdewolff/minify/v2 v2.20.34
|
||||
github.com/yuin/goldmark v1.7.1
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/term v0.21.0
|
||||
golang.org/x/text v0.16.0
|
||||
mvdan.cc/xurls/v2 v2.5.0
|
||||
)
|
||||
|
||||
go 1.16
|
||||
require (
|
||||
github.com/go-webauthn/x v0.1.9 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/google/go-tpm v0.9.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.7.15 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
)
|
||||
|
||||
go 1.22
|
||||
|
|
732
go.sum
732
go.sum
|
@ -1,661 +1,113 @@
|
|||
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
|
||||
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
|
||||
github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
|
||||
github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
|
||||
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.0/go.mod h1:3+D9sFq0ahK/JeJPhCBUV1xlf4/eIYrUQaxulT0VzX8=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-delve/delve v1.5.0/go.mod h1:c6b3a1Gry6x8a4LGCe/CWzrocrfaHvkUxCj3k4bvSUQ=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/gddo v0.0.0-20180823221919-9d8ff1c67be5/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg=
|
||||
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
|
||||
github.com/google/go-dap v0.3.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-server-timing v1.0.2-0.20201108055052-feb680ab92c2 h1:9kYRAm87/M5VL+HWegDGIorBWDiErrZrksLKTJBF2IQ=
|
||||
github.com/mitchellh/go-server-timing v1.0.2-0.20201108055052-feb680ab92c2/go.mod h1:8mKJVJkyMI20ifXXO0zlV3sh3FrtjvltAeBqz38clBE=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||
github.com/go-webauthn/webauthn v0.10.2 h1:OG7B+DyuTytrEPFmTX503K77fqs3HDK/0Iv+z8UYbq4=
|
||||
github.com/go-webauthn/webauthn v0.10.2/go.mod h1:Gd1IDsGAybuvK1NkwUTLbGmeksxuRJjVN2PE/xsPxHs=
|
||||
github.com/go-webauthn/x v0.1.9 h1:v1oeLmoaa+gPOaZqUdDentu6Rl7HkSSsmOT6gxEQHhE=
|
||||
github.com/go-webauthn/x v0.1.9/go.mod h1:pJNMlIMP1SU7cN8HNlKJpLEnFHCygLCvaLZ8a1xeoQA=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
|
||||
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
|
||||
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
|
||||
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/rylans/getlang v0.0.0-20200505200108-4c3188ff8a2d h1:4Jn2kzSKcpxxwpJdyWxfNWKCYe4Uki2VibkExYmBLiA=
|
||||
github.com/rylans/getlang v0.0.0-20200505200108-4c3188ff8a2d/go.mod h1:3vfmZI6aJd5Rb9W2TQ0Nmupl+qem21R05+hmCscI0Bk=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1KMdE=
|
||||
github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk=
|
||||
github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ=
|
||||
github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
|
||||
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
|
||||
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
|
||||
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.starlark.net v0.0.0-20190702223751-32f345186213/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
go.starlark.net v0.0.0-20201006213952-227f4aabceb5/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tdewolff/minify/v2 v2.20.34 h1:XueI6sQtgS7du45fyBCNkNfPQ9SINaYavMFNOxp37SA=
|
||||
github.com/tdewolff/minify/v2 v2.20.34/go.mod h1:L1VYef/jwKw6Wwyk5A+T0mBjjn3mMPgmjjA688RNsxU=
|
||||
github.com/tdewolff/parse/v2 v2.7.15 h1:hysDXtdGZIRF5UZXwpfn3ZWRbm+ru4l53/ajBRGpCTw=
|
||||
github.com/tdewolff/parse/v2 v2.7.15/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
|
||||
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
|
||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
|
||||
mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
|
||||
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright 2022 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package googlereader implements Google Reader API endpoints.
|
||||
*/
|
||||
package googlereader // import "miniflux.app/googlereader"
|
|
@ -1,208 +0,0 @@
|
|||
// Copyright 2022 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package googlereader // import "miniflux.app/googlereader"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"miniflux.app/http/request"
|
||||
"miniflux.app/http/response"
|
||||
"miniflux.app/http/response/json"
|
||||
"miniflux.app/logger"
|
||||
"miniflux.app/model"
|
||||
"miniflux.app/storage"
|
||||
)
|
||||
|
||||
type middleware struct {
|
||||
store *storage.Storage
|
||||
}
|
||||
|
||||
func newMiddleware(s *storage.Storage) *middleware {
|
||||
return &middleware{s}
|
||||
}
|
||||
|
||||
func (m *middleware) clientLogin(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := request.ClientIP(r)
|
||||
var username, password, output string
|
||||
var integration *model.Integration
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
logger.Error("[GoogleReader][Login] [ClientIP=%s] Could not parse form", clientIP)
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
username = r.Form.Get("Email")
|
||||
password = r.Form.Get("Passwd")
|
||||
output = r.Form.Get("output")
|
||||
|
||||
if username == "" || password == "" {
|
||||
logger.Error("[GoogleReader][Login] [ClientIP=%s] Empty username or password", clientIP)
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err = m.store.GoogleReaderUserCheckPassword(username, password); err != nil {
|
||||
logger.Error("[GoogleReader][Login] [ClientIP=%s] Invalid username or password: %s", clientIP, username)
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("[GoogleReader][Login] [ClientIP=%s] User authenticated: %s", clientIP, username)
|
||||
|
||||
if integration, err = m.store.GoogleReaderUserGetIntegration(username); err != nil {
|
||||
logger.Error("[GoogleReader][Login] [ClientIP=%s] Could not load integration: %s", clientIP, username)
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
m.store.SetLastLogin(integration.UserID)
|
||||
|
||||
token := getAuthToken(integration.GoogleReaderUsername, integration.GoogleReaderPassword)
|
||||
logger.Info("[GoogleReader][Login] [ClientIP=%s] Created token: %s", clientIP, token)
|
||||
result := login{SID: token, LSID: token, Auth: token}
|
||||
if output == "json" {
|
||||
json.OK(w, r, result)
|
||||
return
|
||||
}
|
||||
builder := response.New(w, r)
|
||||
builder.WithHeader("Content-Type", "text/plain; charset=UTF-8")
|
||||
builder.WithBody(result.String())
|
||||
builder.Write()
|
||||
}
|
||||
|
||||
func (m *middleware) token(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := request.ClientIP(r)
|
||||
|
||||
if !request.IsAuthenticated(r) {
|
||||
logger.Error("[GoogleReader][Token] [ClientIP=%s] User is not authenticated", clientIP)
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
token := request.GoolgeReaderToken(r)
|
||||
if token == "" {
|
||||
logger.Error("[GoogleReader][Token] [ClientIP=%s] User does not have token: %s", clientIP, request.UserID(r))
|
||||
json.Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
logger.Info("[GoogleReader][Token] [ClientIP=%s] token: %s", clientIP, token)
|
||||
w.Header().Add("Content-Type", "text/plain; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(token))
|
||||
}
|
||||
|
||||
func (m *middleware) handleCORS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization")
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *middleware) apiKeyAuth(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := request.ClientIP(r)
|
||||
|
||||
var token string
|
||||
if r.Method == http.MethodPost {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
logger.Error("[GoogleReader][Login] [ClientIP=%s] Could not parse form", clientIP)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
token = r.Form.Get("T")
|
||||
if token == "" {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Post-Form T field is empty", clientIP)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
authorization := r.Header.Get("Authorization")
|
||||
|
||||
if authorization == "" {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] No token provided", clientIP)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
fields := strings.Fields(authorization)
|
||||
if len(fields) != 2 {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Authorization header does not have the expected structure GoogleLogin auth=xxxxxx - '%s'", clientIP, authorization)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
if fields[0] != "GoogleLogin" {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Authorization header does not begin with GoogleLogin - '%s'", clientIP, authorization)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
auths := strings.Split(fields[1], "=")
|
||||
if len(auths) != 2 {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Authorization header does not have the expected structure GoogleLogin auth=xxxxxx - '%s'", clientIP, authorization)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
if auths[0] != "auth" {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Authorization header does not have the expected structure GoogleLogin auth=xxxxxx - '%s'", clientIP, authorization)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
token = auths[1]
|
||||
}
|
||||
|
||||
parts := strings.Split(token, "/")
|
||||
if len(parts) != 2 {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Auth token does not have the expected structure username/hash - '%s'", clientIP, token)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
var integration *model.Integration
|
||||
var user *model.User
|
||||
var err error
|
||||
if integration, err = m.store.GoogleReaderUserGetIntegration(parts[0]); err != nil {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] token: %s", clientIP, token)
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] No user found with the given google reader username: %s", clientIP, parts[0])
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
expectedToken := getAuthToken(integration.GoogleReaderUsername, integration.GoogleReaderPassword)
|
||||
if expectedToken != token {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] Token does not match: %s", clientIP, token)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
if user, err = m.store.UserByID(integration.UserID); err != nil {
|
||||
logger.Error("[GoogleReader][Auth] [ClientIP=%s] No user found with the userID: %d", clientIP, integration.UserID)
|
||||
Unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
m.store.SetLastLogin(integration.UserID)
|
||||
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, request.UserIDContextKey, user.ID)
|
||||
ctx = context.WithValue(ctx, request.UserTimezoneContextKey, user.Timezone)
|
||||
ctx = context.WithValue(ctx, request.IsAdminUserContextKey, user.IsAdmin)
|
||||
ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)
|
||||
ctx = context.WithValue(ctx, request.GoogleReaderToken, token)
|
||||
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func getAuthToken(username, password string) string {
|
||||
token := hex.EncodeToString(hmac.New(sha1.New, []byte(username+password)).Sum(nil))
|
||||
token = username + "/" + token
|
||||
return token
|
||||
}
|
|
@ -1,343 +0,0 @@
|
|||
// Copyright 2018 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package client // import "miniflux.app/http/client"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"miniflux.app/config"
|
||||
"miniflux.app/errors"
|
||||
"miniflux.app/logger"
|
||||
"miniflux.app/timer"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultHTTPClientTimeout = 20
|
||||
defaultHTTPClientMaxBodySize = 15 * 1024 * 1024
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidCertificate = "Invalid SSL certificate (original error: %q)"
|
||||
errNetworkOperation = "This website is unreachable (original error: %q)"
|
||||
errRequestTimeout = "Website unreachable, the request timed out after %d seconds"
|
||||
)
|
||||
|
||||
// Client builds and executes HTTP requests.
|
||||
type Client struct {
|
||||
inputURL string
|
||||
|
||||
requestEtagHeader string
|
||||
requestLastModifiedHeader string
|
||||
requestAuthorizationHeader string
|
||||
requestUsername string
|
||||
requestPassword string
|
||||
requestUserAgent string
|
||||
requestCookie string
|
||||
|
||||
useProxy bool
|
||||
doNotFollowRedirects bool
|
||||
|
||||
ClientTimeout int
|
||||
ClientMaxBodySize int64
|
||||
ClientProxyURL string
|
||||
AllowSelfSignedCertificates bool
|
||||
}
|
||||
|
||||
// New initializes a new HTTP client.
|
||||
func New(url string) *Client {
|
||||
return &Client{
|
||||
inputURL: url,
|
||||
ClientTimeout: defaultHTTPClientTimeout,
|
||||
ClientMaxBodySize: defaultHTTPClientMaxBodySize,
|
||||
}
|
||||
}
|
||||
|
||||
// NewClientWithConfig initializes a new HTTP client with application config options.
|
||||
func NewClientWithConfig(url string, opts *config.Options) *Client {
|
||||
return &Client{
|
||||
inputURL: url,
|
||||
requestUserAgent: opts.HTTPClientUserAgent(),
|
||||
ClientTimeout: opts.HTTPClientTimeout(),
|
||||
ClientMaxBodySize: opts.HTTPClientMaxBodySize(),
|
||||
ClientProxyURL: opts.HTTPClientProxy(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) String() string {
|
||||
etagHeader := c.requestEtagHeader
|
||||
if c.requestEtagHeader == "" {
|
||||
etagHeader = "None"
|
||||
}
|
||||
|
||||
lastModifiedHeader := c.requestLastModifiedHeader
|
||||
if c.requestLastModifiedHeader == "" {
|
||||
lastModifiedHeader = "None"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
`InputURL=%q ETag=%s LastMod=%s Auth=%v UserAgent=%q Verify=%v`,
|
||||
c.inputURL,
|
||||
etagHeader,
|
||||
lastModifiedHeader,
|
||||
c.requestAuthorizationHeader != "" || (c.requestUsername != "" && c.requestPassword != ""),
|
||||
c.requestUserAgent,
|
||||
!c.AllowSelfSignedCertificates,
|
||||
)
|
||||
}
|
||||
|
||||
// WithCredentials defines the username/password for HTTP Basic authentication.
|
||||
func (c *Client) WithCredentials(username, password string) *Client {
|
||||
if username != "" && password != "" {
|
||||
c.requestUsername = username
|
||||
c.requestPassword = password
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// WithAuthorization defines the authorization HTTP header value.
|
||||
func (c *Client) WithAuthorization(authorization string) *Client {
|
||||
c.requestAuthorizationHeader = authorization
|
||||
return c
|
||||
}
|
||||
|
||||
// WithCacheHeaders defines caching headers.
|
||||
func (c *Client) WithCacheHeaders(etagHeader, lastModifiedHeader string) *Client {
|
||||
c.requestEtagHeader = etagHeader
|
||||
c.requestLastModifiedHeader = lastModifiedHeader
|
||||
return c
|
||||
}
|
||||
|
||||
// WithProxy enables proxy for the current HTTP request.
|
||||
func (c *Client) WithProxy() *Client {
|
||||
c.useProxy = true
|
||||
return c
|
||||
}
|
||||
|
||||
// WithoutRedirects disables HTTP redirects.
|
||||
func (c *Client) WithoutRedirects() *Client {
|
||||
c.doNotFollowRedirects = true
|
||||
return c
|
||||
}
|
||||
|
||||
// WithUserAgent defines the User-Agent header to use for HTTP requests.
|
||||
func (c *Client) WithUserAgent(userAgent string) *Client {
|
||||
if userAgent != "" {
|
||||
c.requestUserAgent = userAgent
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// WithCookie defines the Cookies to use for HTTP requests.
|
||||
func (c *Client) WithCookie(cookie string) *Client {
|
||||
if cookie != "" {
|
||||
c.requestCookie = cookie
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Get performs a GET HTTP request.
|
||||
func (c *Client) Get() (*Response, error) {
|
||||
request, err := c.buildRequest(http.MethodGet, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.executeRequest(request)
|
||||
}
|
||||
|
||||
// PostForm performs a POST HTTP request with form encoded values.
|
||||
func (c *Client) PostForm(values url.Values) (*Response, error) {
|
||||
request, err := c.buildRequest(http.MethodPost, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
return c.executeRequest(request)
|
||||
}
|
||||
|
||||
// PostJSON performs a POST HTTP request with a JSON payload.
|
||||
func (c *Client) PostJSON(data interface{}) (*Response, error) {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request, err := c.buildRequest(http.MethodPost, bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
return c.executeRequest(request)
|
||||
}
|
||||
|
||||
func (c *Client) executeRequest(request *http.Request) (*Response, error) {
|
||||
defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[HttpClient] inputURL=%s", c.inputURL))
|
||||
|
||||
logger.Debug("[HttpClient:Before] Method=%s %s",
|
||||
request.Method,
|
||||
c.String(),
|
||||
)
|
||||
|
||||
client := c.buildClient()
|
||||
resp, err := client.Do(request)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if uerr, ok := err.(*url.Error); ok {
|
||||
switch uerr.Err.(type) {
|
||||
case x509.CertificateInvalidError, x509.HostnameError:
|
||||
err = errors.NewLocalizedError(errInvalidCertificate, uerr.Err)
|
||||
case *net.OpError:
|
||||
err = errors.NewLocalizedError(errNetworkOperation, uerr.Err)
|
||||
case net.Error:
|
||||
nerr := uerr.Err.(net.Error)
|
||||
if nerr.Timeout() {
|
||||
err = errors.NewLocalizedError(errRequestTimeout, c.ClientTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.ContentLength > c.ClientMaxBodySize {
|
||||
return nil, fmt.Errorf("client: response too large (%d bytes)", resp.ContentLength)
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("client: error while reading body %v", err)
|
||||
}
|
||||
|
||||
response := &Response{
|
||||
Body: bytes.NewReader(buf),
|
||||
StatusCode: resp.StatusCode,
|
||||
EffectiveURL: resp.Request.URL.String(),
|
||||
LastModified: resp.Header.Get("Last-Modified"),
|
||||
ETag: resp.Header.Get("ETag"),
|
||||
Expires: resp.Header.Get("Expires"),
|
||||
ContentType: resp.Header.Get("Content-Type"),
|
||||
ContentLength: resp.ContentLength,
|
||||
}
|
||||
|
||||
logger.Debug("[HttpClient:After] Method=%s %s; Response => %s",
|
||||
request.Method,
|
||||
c.String(),
|
||||
response,
|
||||
)
|
||||
|
||||
// Ignore caching headers for feeds that do not want any cache.
|
||||
if resp.Header.Get("Expires") == "0" {
|
||||
logger.Debug("[HttpClient] Ignore caching headers for %q", response.EffectiveURL)
|
||||
response.ETag = ""
|
||||
response.LastModified = ""
|
||||
}
|
||||
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (c *Client) buildRequest(method string, body io.Reader) (*http.Request, error) {
|
||||
request, err := http.NewRequest(method, c.inputURL, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request.Header = c.buildHeaders()
|
||||
|
||||
if c.requestUsername != "" && c.requestPassword != "" {
|
||||
request.SetBasicAuth(c.requestUsername, c.requestPassword)
|
||||
}
|
||||
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *Client) buildClient() http.Client {
|
||||
client := http.Client{
|
||||
Timeout: time.Duration(c.ClientTimeout) * time.Second,
|
||||
}
|
||||
|
||||
transport := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
// Default is 30s.
|
||||
Timeout: 10 * time.Second,
|
||||
|
||||
// Default is 30s.
|
||||
KeepAlive: 15 * time.Second,
|
||||
}).DialContext,
|
||||
|
||||
// Default is 100.
|
||||
MaxIdleConns: 50,
|
||||
|
||||
// Default is 90s.
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
if c.AllowSelfSignedCertificates {
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
|
||||
if c.doNotFollowRedirects {
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
}
|
||||
|
||||
if c.useProxy && c.ClientProxyURL != "" {
|
||||
proxyURL, err := url.Parse(c.ClientProxyURL)
|
||||
if err != nil {
|
||||
logger.Error("[HttpClient] Proxy URL error: %v", err)
|
||||
} else {
|
||||
logger.Debug("[HttpClient] Use proxy: %s", proxyURL)
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
}
|
||||
|
||||
client.Transport = transport
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *Client) buildHeaders() http.Header {
|
||||
headers := make(http.Header)
|
||||
headers.Add("Accept", "*/*")
|
||||
|
||||
if c.requestUserAgent != "" {
|
||||
headers.Add("User-Agent", c.requestUserAgent)
|
||||
}
|
||||
|
||||
if c.requestEtagHeader != "" {
|
||||
headers.Add("If-None-Match", c.requestEtagHeader)
|
||||
}
|
||||
|
||||
if c.requestLastModifiedHeader != "" {
|
||||
headers.Add("If-Modified-Since", c.requestLastModifiedHeader)
|
||||
}
|
||||
|
||||
if c.requestAuthorizationHeader != "" {
|
||||
headers.Add("Authorization", c.requestAuthorizationHeader)
|
||||
}
|
||||
|
||||
if c.requestCookie != "" {
|
||||
headers.Add("Cookie", c.requestCookie)
|
||||
}
|
||||
|
||||
headers.Add("Connection", "close")
|
||||
return headers
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue