From daac9f8ccba0c24d16cf619ec7c546a0962d25a7 Mon Sep 17 00:00:00 2001 From: "Daniele Verducci (Slimpenguin)" Date: Tue, 28 Feb 2023 22:18:48 +0100 Subject: [PATCH] First working version --- LICENSE | 674 +++++++++++++++++++++++++++++++++++++ README.md | 36 ++ fetch-dashboard.sh.example | 7 + images/readme-image.jpg | Bin 0 -> 48347 bytes mastodon-image-fetcher.py | 111 ++++++ 5 files changed, 828 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100755 fetch-dashboard.sh.example create mode 100644 images/readme-image.jpg create mode 100755 mastodon-image-fetcher.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..296b717 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Mastodon image fetcher for kindle-dash + +This is really only a script that fetches the last non-CW image from Mastodon, fits to your screen dimensions and writes it to a PNG file. +This is meant to be used with [kidle-dash](https://github.com/pascalw/kindle-dash), but you can use it in other linux-based ebook readers or in any case you may need the last post image saved to a file. + +![Kindle dashboard showing Mastodon post image](images/readme-image.jpg) + +## Install (with kindle-dash) + +You will need a jailbroken kindle. + +Follow the [kidle-dash](https://github.com/pascalw/kindle-dash) instructions to install the dashboard. From now on, let's say you installed it in a folder called `my-dashboard`. + +(Install Python3)[https://wiki.mobileread.com/wiki/Python_on_Kindle] on your kindle +Check python is correctly installed running `python3 --version` (should print something like `Python 3.9.8`). + +> Note: Python version 3.x is required. This will not work with Python 2.x + +Copy `fetch-dashboard.sh.example` in `my-dashboard/local/fetch-dashboard.sh` (you will overwrite an already present file). + +Open `mastodon-image-fetcher.py` and set your Kindle's screen resolution in the Config section (if you don't know it, you can find it running `eips -i` on the kindle terminal). + +Copy `mastodon-image-fetcher.py` in `my-dashboard/local/mastodon-image-fetcher.py` + +Start the dashboard as explained in kindle-dash documentation (running `my-dashboard/start.sh`) + +### Troubleshooting + +Kindle-dash saves a logfile in `my-dashboard/logs/dash.log`. + +## Install (generic) +Just open `mastodon-image-fetcher.py` and set the preferred screen resolution in the Config section. + +## Optimizations + +The image is converted in BW and saved in PNG format, because some ancient utilities for e-ink screens (like the Kindle's `eips` commad) do not support fancier formats, like progressive JPEG (one of the most common image format on the modern Internet). diff --git a/fetch-dashboard.sh.example b/fetch-dashboard.sh.example new file mode 100755 index 0000000..9901f40 --- /dev/null +++ b/fetch-dashboard.sh.example @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +# This is an example configuration for https://github.com/pascalw/kindle-dash +# Ignore this file if you are using a different dashboard + +# Run the fetcher and save result PNG in $1 +python3 "$(dirname "$0")/mastodon-image-fetcher.py" "$1" diff --git a/images/readme-image.jpg b/images/readme-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d42c6e7b3a38f870cd7ef103311d8e4993313e17 GIT binary patch literal 48347 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

<-@(d)uw@#1? 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 + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +import requests +import json +import sys +from io import BytesIO +from PIL import Image + +# CONFIG +mastodonInstanceUrl = "https://mastodon.uno" +imageFileName = "image.png" +# You can find your kindle screen resolution with the command `eips -i` +kindleResolutionWidth = 768 +kindleResolutionHeight = 1024 +# /CONFIG + + +# Get output filename from cli +if len(sys.argv) > 1: + imageFileName = sys.argv[1] + +# Obtain mastodon statuses json +statusesReqUrl = "{}/api/v1/timelines/public?only_media=true".format(mastodonInstanceUrl) +resp = requests.get(statusesReqUrl) +if resp.status_code != 200: + print("Error fetching posts") + exit(1) + +# Get last post photo +statuses = resp.json() +attachUrl = None +for status in statuses: + if status['sensitive']: + continue + if len(status['media_attachments']) > 0: + attachUrl = status['media_attachments'][0]['url'] + if not attachUrl.endswith(".jpg"): + continue + break + +if attachUrl == None: + print("None of the last posts has media!") + exit(0) + +# Dowload post photo +imgBytesResp = requests.get(attachUrl) +if imgBytesResp.status_code != 200: + print("Error downloading post photo {}".format(attachUrl)) + exit(1) + +# Convert to B&W +img = Image.open(BytesIO(imgBytesResp.content)) +img = img.convert( + mode='L' # B&W +) + +# Resize to a square based on kindle screen height (needed to fit image to entire screen) +(width, height) = img.size +ratio = width / height +kindleRatio = kindleResolutionWidth / kindleResolutionHeight +cropLeft = 0 +cropTop = 0 +cropRight = kindleResolutionWidth +cropBottom = kindleResolutionHeight +print("Image size is {}x{}, ratio is {}, kindle ratio is {}".format(width, height, ratio, kindleRatio)) +if ratio > kindleRatio: + # Fit height + destHeight = kindleResolutionHeight + destWidth = width * ratio + # Calc crop + cropLeft = (destWidth - kindleResolutionWidth) / 2 + cropRight = cropLeft + kindleResolutionWidth +else: + # Fit width + destWidth = kindleResolutionWidth + destHeight = height * (1 / ratio) + # Calc crop + cropTop = (destHeight - kindleResolutionHeight) / 2 + cropBottom = cropTop + kindleResolutionHeight + +# Resize +img = img.resize( + (int(destWidth), int(destHeight)) +) + +# Crop +img = img.crop( + (int(cropLeft), int(cropTop), int(cropRight), int(cropBottom)) +) + +img.save(imageFileName, "PNG") +print("Saved {}".format(imageFileName))