19 Commits

Author SHA1 Message Date
2eeaa34401 working 2025-06-05 19:28:25 +00:00
9bd34aeb2a fixed
All checks were successful
QuotesBot / deploy (push) Successful in 32s
2025-06-05 19:26:01 +00:00
99d307a2a7 debug line
Some checks failed
QuotesBot / deploy (push) Failing after 24s
2025-06-05 19:19:34 +00:00
b412eafc97 debug line 2025-06-05 19:18:43 +00:00
2e3c034eed think i fixed it 2025-06-05 19:01:02 +00:00
e593c71fc1 fix workflow badge
All checks were successful
QuotesBot / deploy (push) Successful in 36s
2025-06-05 10:22:56 -05:00
a159c7ff8e fix workflow badge 2025-06-05 10:21:50 -05:00
e10082d96c fix workflow 2025-06-05 08:33:35 -05:00
f48dd5dcf5 fix workflow 2025-06-05 08:28:56 -05:00
9b00d5d6ee tweaks 2025-06-05 05:36:27 -05:00
467defdffe error in field name 2025-06-05 05:35:07 -05:00
3ed5ef7079 Update .gitea/workflows/deploy.yml 2025-06-05 05:19:17 -05:00
05218ad6b2 update README 2025-06-05 05:15:20 -05:00
83662cd415 error in field name 2025-06-05 05:12:59 -05:00
1213e08c7b forgot the hashtags 2025-06-05 05:09:27 -05:00
8605f7f732 add a badge; not sure if it works yet 2025-06-05 05:08:11 -05:00
20feb33632 whoops - error in the workflow 2025-06-05 04:47:02 -05:00
c7cb0dfff6 re-add quotesbot profile link 2025-06-05 04:38:19 -05:00
d498f50b6a complete overhaul of the bot 2025-06-05 04:34:37 -05:00
10 changed files with 309 additions and 47 deletions

48
.archive/README.md Normal file
View File

@ -0,0 +1,48 @@
# @quotesbot
This is the code that posts to https://bots.fyrfli.social/@quotesbot.
## Requirements:
- some knowledge of the linux command line
- python installed
- a Mastodon-compatible API token for your instance
- a json-formatted file of quotes to use formatted thus:
```
[
{
"quote": "quote",
"author": "author"
},
...
{
"quote": "quote",
"author": "author"
}
]
```
Your quotes file can either be in the local directory or accessible at a url.
## To install:
- Download the release package
- Extract into your chosen directory:
- `mkdir quotesbot && cd quotesbot`
- `tar xfz | gunzip source.[zip|tar.gz]`
- If you have other projects, you can create a virtual environment to run this code:
- `python3 -m venv .venv`
- `source .venv/bin/activate`
- `python3 -m pip install -r requirements.txt`
- Otherwise, just install from the requirements.txt: `python3 -m pip install -r requirements.txt`
- Copy the env.example to .env and change the values to your own
## To use:
- You can either run the code without any arguments: `python3 random_quotes.py` or you can pass **one** argument through to the code to select a specific quote to post:
- `python3 random_quotes.py 1`
## Caveats
This is code is *very* rudimentary. It serves a specific purpose:
- To post my favourite quotes to my timeline every few hours
- To practice my python coding skills
## Going forward
It is possible that I may continue to work on this to a point where it's a more sophisticated module, but I can almost guarantee that there are packages out there that do this and more with far more finesse.

View File

@ -0,0 +1,6 @@
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
python-dotenv==1.0.1
requests==2.31.0
urllib3==2.2.1

View File

@ -0,0 +1,24 @@
name: QuotesBot
on:
schedule:
- cron: '35 */4 * * *'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run app.py
run:
python app.py
env:
POST_TOKEN: ${{ secrets.POST_TOKEN }}
POST_ENDPOINT: ${{ secrets.POST_ENDPOINT }}
SOURCE_ENDPOINT: ${{ secrets.SOURCE_ENDPOINT }}

12
Pipfile Normal file
View File

@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
requests = "*"
[dev-packages]
[requires]
python_version = "3.13"

152
Pipfile.lock generated Normal file
View File

@ -0,0 +1,152 @@
{
"_meta": {
"hash": {
"sha256": "1841259a6294939b3dde91acf33c2e02af40cae97022c9b3da3f7f2bb07c77c5"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.13"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"certifi": {
"hashes": [
"sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6",
"sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"
],
"markers": "python_version >= '3.6'",
"version": "==2025.4.26"
},
"charset-normalizer": {
"hashes": [
"sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4",
"sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45",
"sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7",
"sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0",
"sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7",
"sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d",
"sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d",
"sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0",
"sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184",
"sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db",
"sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b",
"sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64",
"sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b",
"sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8",
"sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff",
"sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344",
"sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58",
"sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e",
"sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471",
"sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148",
"sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a",
"sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836",
"sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e",
"sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63",
"sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c",
"sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1",
"sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01",
"sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366",
"sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58",
"sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5",
"sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c",
"sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2",
"sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a",
"sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597",
"sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b",
"sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5",
"sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb",
"sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f",
"sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0",
"sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941",
"sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0",
"sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86",
"sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7",
"sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7",
"sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455",
"sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6",
"sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4",
"sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0",
"sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3",
"sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1",
"sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6",
"sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981",
"sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c",
"sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980",
"sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645",
"sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7",
"sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12",
"sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa",
"sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd",
"sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef",
"sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f",
"sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2",
"sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d",
"sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5",
"sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02",
"sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3",
"sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd",
"sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e",
"sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214",
"sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd",
"sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a",
"sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c",
"sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681",
"sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba",
"sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f",
"sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a",
"sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28",
"sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691",
"sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82",
"sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a",
"sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027",
"sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7",
"sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518",
"sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf",
"sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b",
"sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9",
"sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544",
"sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da",
"sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509",
"sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f",
"sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a",
"sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"
],
"markers": "python_version >= '3.7'",
"version": "==3.4.2"
},
"idna": {
"hashes": [
"sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
"sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
],
"markers": "python_version >= '3.6'",
"version": "==3.10"
},
"requests": {
"hashes": [
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
"urllib3": {
"hashes": [
"sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466",
"sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"
],
"markers": "python_version >= '3.9'",
"version": "==2.4.0"
}
},
"develop": {}
}

View File

@ -1,48 +1,46 @@
# @quotesbot
# The new [QuotesBot](https://bots.fyrfli.social/@quotesbot) code ![](https://fyrfli.dev/fyrfli/quotesbot/actions/workflows/deploy.yml/badge.svg)
This is the code that posts to https://bots.fyrfli.social/@quotesbot.
In the neverending quest to improve my coding skills, I often check out the code that other bots employ. Last night, I decided to check out the code for the [ThursdayBot](https://github.com/devashishp/thursday) and realised something really neat:
## Requirements:
- some knowledge of the linux command line
- python installed
- a Mastodon-compatible API token for your instance
- a json-formatted file of quotes to use formatted thus:
```
[
{
"quote": "quote",
"author": "author"
},
...
{
"quote": "quote",
"author": "author"
}
]
```
Your quotes file can either be in the local directory or accessible at a url.
>[!IMPORTANT]
>***there is a way to make the bot completely foolproof!!!***
## To install:
Without delay, I tested it out for myself and when I was satisfied, updated this repository to take over from the cronjob I was using. The old code is still available under the .archive subdirectory and will be for a few weeks.
- Download the release package
- Extract into your chosen directory:
- `mkdir quotesbot && cd quotesbot`
- `tar xfz | gunzip source.[zip|tar.gz]`
- If you have other projects, you can create a virtual environment to run this code:
- `python3 -m venv .venv`
- `source .venv/bin/activate`
- `python3 -m pip install -r requirements.txt`
- Otherwise, just install from the requirements.txt: `python3 -m pip install -r requirements.txt`
- Copy the env.example to .env and change the values to your own
## What does it do?
## To use:
- You can either run the code without any arguments: `python3 random_quotes.py` or you can pass **one** argument through to the code to select a specific quote to post:
- `python3 random_quotes.py 1`
Posts a quote every 4 hours from a file that you specify.
## Caveats
This is code is *very* rudimentary. It serves a specific purpose:
- To post my favourite quotes to my timeline every few hours
- To practice my python coding skills
## To do
- enable using a software forge to store the CSV-formatted text file with your list of quotes.
- maybe use a secret to customise the run schedule
## Going forward
It is possible that I may continue to work on this to a point where it's a more sophisticated module, but I can almost guarantee that there are packages out there that do this and more with far more finesse.
## Customising for your own use
### Requirements
- an account on an ActivityPub instance like Mastodon
- a developer token (which can be issued from your settings page - on Mastodon that is https://your-instance.url/settings/applications)
- a CSV-Formatted file stored online somewhere
- the CSV-Formatted file should include two (2) columns: "quote" and "author" (in that order) like:
```
quote,author
"Amet lorem voluptatem tempore sint quod? Nam porro aliquid aspernatur assumenda fugiat A odit excepturi facere vero nihil Nulla voluptate accusantium vero recusandae nulla Obcaecati nemo dolor non reprehenderit excepturi23", "Example Author"
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla","Author Exemplaris",
...
```
### Steps
- clone the repository to any software forge that supoorts the use of Github-style action.
- you will need an account of your own
- the ones that I know of right now are:
- self-hosted [gitea](https://giteo.io), [forgejo](https://forgejo.org), and -of course- [github](https://github.com)
- create your secrets:
- POST_TOKEN: an API development token from your Mastodon API-compatible ActivityPub software instance
- POST_ENDPOINT: https://your-instance.url/api/v1/statuses
- SOURCE_ENDPOINT: a link to an online text file in CSV format
- wait and watch your bot account for posts
Enjoy!!

22
app.py Normal file
View File

@ -0,0 +1,22 @@
from requests import get, post
from json import loads, dumps
from os import getenv
from random import randint
import csv, io
post_token = getenv('POST_TOKEN')
post_endpoint = getenv('POST_ENDPOINT')
source_token = getenv('SOURCE_TOKEN')
source_endpoint = getenv('SOURCE_ENDPOINT')
source_object = get(source_endpoint)
if source_object.reason == "OK":
reader = csv.DictReader(io.StringIO(source_object.text))
source_data = dumps(list(reader))
choices = loads(source_data)
choice = choices[randint(0, len(choices) - 1)]
headers = {'Authorization': 'Bearer ' + post_token}
payload = {'status': f"{choice['quote']}\n\n - {choice['author']}\n\n#RandomQuote #quotes #quote #bot", 'visibility': 'public'}
response = post(post_endpoint, headers=headers, data=payload)
print(response.reason)
print(loads(response.text)['url'])

View File

@ -1,6 +1,6 @@
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
python-dotenv==1.0.1
requests==2.31.0
urllib3==2.2.1
-i https://pypi.org/simple
certifi==2025.4.26; python_version >= '3.6'
charset-normalizer==3.4.2; python_version >= '3.7'
idna==3.10; python_version >= '3.6'
requests==2.32.3; python_version >= '3.8'
urllib3==2.4.0; python_version >= '3.9'