La versione italiana si trova sotto quella inglese
The italian version is under the english one
Adding Features and Trying New Stuff to Bring My Script to Its Final Form!
After several days of work, today I finally managed to finish all the “upgrades” I planned to do to my script.
As I have said several times, the purpose of my project is to automate as much as possible the process of selection of eligible posts for the contest held each week by the @balaenoptera account.
To do this, I initially focused on what were the main requirements:
- the post must have been published within the Olio di Balena community;
- no more than 7 days must have passed since its publication;
- it must contain at least 500 words, for single-language posts, or at least 1,000, for dual-language posts;
- must have been written by an author who has expressed his/her preference at least once in the previous three polls hosted by @balaenoptera;
- it must have been written by an author who has written at least one comment under a post published in the last 7 days in Whale Oil by another author.
Implementing all these checks was a real challenge but, after about a month of work, my script began to produce the first results, generating a reliable list of valid posts.
At this point, however, a new challenge presented itself: in fact, when there are many posts, some more criteria come to the rescue to pick the 4 who will join the challenge.
New requirements to be checked!
These criteria are in addition to and different from those listed above, and with the intention to automate as many checks as possible, I took the decision to go one step further and try to add new features to my script that would take care of checking these requirements as well, i.e:
- the number of comments posted in Olio di Balena by the selected authors in the last 7 days;
- the number of votes cast by selected authors in the last 3 polls;
- having set @balaenoptera as a beneficiary;
- the number of times one has arelady won a contest (where those who have won less than others have more chance to be selected).
After doing a bit of reasoning, I quickly realized that verifying the first 3 criteria would have been easy, since my script actually already retrieved some of this data, so all I had to do was change a few lines of code here and there and... voila! Now this information is also correctly recorded and made available to the user.
What posed a real challenge, however, was the 4th criteria: figuring out how to identify the winner of a contest took me several days, because posts often announce it differently (so I can't, for example, always search for a certain phrase to see which username appears there) and there is also no way to see and retrieve the number of votes placed in a poll...
How to do it then?
Days and days of pondering, when I finally had an epiphany!
Winners of a contest are set as beneficiaries (60%, if one, or 30%, if two) of @balaenoptera's next post: so all I had to do was retrieve this information to find myself, at last, with a list of all past winners, as well as a way to automatically identify future ones as well.
And in the process I also learned new stuff!
All this adding features and solving different problems has also led me to raise doubts and questions whose solution has often been made possible by the use of new tools or by deepening those I already knew: manipulating files is becoming something I'm starting to do with more confidence; the number of libraries I know and have used at least once is increasing; even splitting some more complex functions into different files and then importing them where I need is something I have, for the first time, been able to test and implement in my script.
This is small progress, but slowly I hope it will lead me to better and better results :)
Some snippets
To conclude, a post on Hive and Python would not be such without some snippets to share!
So here's the heart of the script I wrote to keep track of previous contest winners: I know it's a bit messy work, but after I got the inspiration I got to work on it for a few hours and I didn't have time to make it a bit more readable... I still hope it gives you an idea of how it all works!
# Get and update list of users who won at least a contest
def get_contest_winners(session: requests.Session):
# Get replies from target author
data = (
f'{{"jsonrpc":"2.0", "method":"bridge.get_account_posts", '
f'"params":{{"sort":"posts", "account": "balaenoptera", "limit": 100}}, "id":1}}'
)
posts = get_response(data, session)
winners = []
with open("winners.txt", "r", newline="", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line:
winner_dict = ast.literal_eval(line)
winners.append(winner_dict)
logger.info(f"Previous winners:\n{winners}")
new_posts_num = 0
for post in posts:
if post["created"] == winners[0]["timestamp"]:
break
new_posts_num += 1
if new_posts_num == 0:
print("No new posts from @balaenoptera found")
return False
else:
print(
f"Found {new_posts_num} new posts from @baleanoptera: updating winners list..."
)
winners[0]["timestamp"] = posts[0]["created"]
for post in posts[:new_posts_num]:
beneficiaries = post["beneficiaries"]
for beneficiary in beneficiaries:
if (
beneficiary["weight"] == 3000
or beneficiary["weight"] == 6000
or beneficiary["weight"] == 6500
):
winner_found = False
for winner in winners:
if winner.get("author", []) == beneficiary["account"]:
winner["wins"] += 1
winner_found = True
break
if not winner_found:
winners.append({"author": beneficiary["account"], "wins": 1})
return winners
def update_winners_list(session: requests.Session):
hall_of_fame = get_contest_winners(session)
if hall_of_fame:
with open("winners.txt", "w", newline="", encoding="utf-8") as file:
for winner in hall_of_fame:
file.write(json.dumps(winner) + "\n")
logger.info("Winners list updated")
And this is the generated list, which is updated every time the script is run and detects a new post by @balaenoptera
{"timestamp": "2024-10-26T00:12:36"}
{"author": "arc7icwolf", "wins": 7}
{"author": "stefano.massari", "wins": 2}
{"author": "bencwarmer", "wins": 4}
{"author": "vittoriozuccala", "wins": 2}
{"author": "lozio71", "wins": 1}
{"author": "p1k4ppa10", "wins": 3}
{"author": "mad-runner", "wins": 1}
{"author": "pousinha", "wins": 2}
{"author": "stewie.wieno", "wins": 4}
{"author": "giuatt07", "wins": 1}
{"author": "tosolini", "wins": 2}
{"author": "li-lou", "wins": 1}
And if you'd like to poke around through the full code, I've finally uploaded and shared everything on GitHub!
You can find the complete and updated repository here!
cover made with Bing AI and edited with GIMP
to support the #OliodiBalena community, @balaenoptera is 3% beneficiary of this post
If you've read this far, thank you! If you want to leave an upvote, a reblog, a follow, a comment... well, any sign of life is really much appreciated!
Versione italiana
Italian version
Aggiungendo Funzioni e Testando Nuove Possibilità per Elevare il Mio Script alla sua Forma Finale!
Dopo svariati giorni di lavoro, oggi sono finalmente riuscito a terminare tutti gli "upgrades" che avevo deciso di apportare al mio script.
Come ho detto varie volte, lo scopo del mio progetto è quello di automatizzare quanto più possibile la selezione dei posts eleggibili per il contest organizzato ogni settimana dall'account @balaenoptera.
Per farlo mi sono inizialmente concentrato su quelli che erano i requisiti essenziali (e suscettibili di automatizzazione):
- il post deve essere stato pubblicato all'interno della comunità di Olio di Balena;
- non devono essere passati più di 7 giorni dalla sua pubblicazione;
- deve contenere almeno 500 parole, per i post in singola lingua, o almeno 1000, per i post in doppia lingua;
- deve essere stato scritto da un autore che ha espresso la sua preferenza almeno una volta nei precedenti tre sondaggi organizzati da @balaenoptera;
- deve essere stato scritto da un autore che ha scritto almeno un commento sotto un post pubblicato negli ultimi 7 giorni in Olio di Balena da un altro autore.
Implementare tutti questi controlli è stata una vera sfida ma, dopo circa un mese di lavoro, il mio script ha cominciato a produrre i primi risultati, generando una lista attendibile di posts validi ai fini del contest.
A questo punto, però, si è presentata una nuova sfida: quando infatti i post sono tanti, per selezionare i 4 che parteciperanno alla sfida vengono in aiuto alcuni criteri di preferenza.
Nuovi requisiti da controllare!
Questi criteri sono ulteriori e diversi da quelli elencati sopra e, con l'obiettivo di automatizzare quanti più controlli possibili, ho deciso di fare un altro passo in avanti e provare ad aggiungere nuove funzioni al mio script che si occupassero di verificare anche questi aspetti, ossia:
- il numero di commenti pubblicati in Olio di Balena dagli autori selezionati negli ultimi 7 giorni;
- il numero di voti espressi dagli autori selezionati negli ultimi 3 sondaggi;
- l'aver settato @balaenoptera come beneficiario;
- il numero di volte in cui qualcuno ha già vinto un contest (dove ha più chances di essere selezionato chi ha vinto meno degli altri).
Dopo aver fatto un po' di ragionamenti, ho subito capito che verificare i primi 3 criteri di preferenza sarebbe stato facile, dato che il mio script, in realtà, già recuperava in parte questi dati, per cui mi è bastato cambiare qualche riga di codice qui e là e... voilà! Ora anche queste informazioni vengono correttamente registrate e messe a disposizione dell'utente.
Ciò che invece ha rappresentato una vera sfida è stato il 4° criterio di preferenza: capire come individuare il vincitore di un contest mi ha richiesto vari giorni, perchè i post lo annunciano spesso in modo diverso (per cui non posso, ad esempio, ricercare sempre una certa frase per vedere quale è lo username che compare lì) e non c'è nemmeno un modo per vedere e recuperare il numero di voti espressi in un sondaggio...
Come fare allora?
Giorni e giorni di pensieri, quando finalmente ho avuto l'illuminazione!
I vincitori di un contest vengono impostati come beneficiari (al 60%, se uno, o 30%, se in due) del successivo post pubblicato di @balaenoptera: mi è quindi bastato recuperare questa informazione per ritrovarmi, finalmente con la lista di tutti i passati vincitori, nonchè con un modo per automatizzare anche l'identificazione di quelli futuri.
E nel mentre ho anche imparato cose nuove!
Tutto questo aggiungere funzioni e risolvere problemi diversi mi ha anche portato a pormi dubbi e domande la cui soluzione spesso è stata resa possibile dall'utilizzo di nuovi strumenti o dall'approfondimento di quelli che già conoscevo: manipolare file sta diventando qualcosa che comincio a fare con maggior dimestichezza; aumentano le librerie che conosco e che ho utilizzato almeno una volta; anche separare certe funzioni più complesse in file diversi per poi importarle dove mi servono è un qualcosa che ho, per la prima volta, potuto testare ed implementare nel mio script.
Sono piccoli progressi, ma piano piano spero che mi portino a risultati sempre migliori :)
Alcuni snippets
Per concludere, un post su Hive e Python non sarebbe tale senza un po' di snippets da convidere!
Ecco allora il cuore dello script che ho scritto per tenere traccia dei precedenti vincitori del contest: so che è un lavoro un po' caotico, ma dopo aver avuto l'illuminazione mi ci sono messo al lavoro per alcune ore e non ho avuto il tempo di renderlo un po' più leggibile... spero comunque che renda l'idea di come funziona il tutto!
# Get and update list of users who won at least a contest
def get_contest_winners(session: requests.Session):
# Get replies from target author
data = (
f'{{"jsonrpc":"2.0", "method":"bridge.get_account_posts", '
f'"params":{{"sort":"posts", "account": "balaenoptera", "limit": 100}}, "id":1}}'
)
posts = get_response(data, session)
winners = []
with open("winners.txt", "r", newline="", encoding="utf-8") as file:
for line in file:
line = line.strip()
if line:
winner_dict = ast.literal_eval(line)
winners.append(winner_dict)
logger.info(f"Previous winners:\n{winners}")
new_posts_num = 0
for post in posts:
if post["created"] == winners[0]["timestamp"]:
break
new_posts_num += 1
if new_posts_num == 0:
print("No new posts from @balaenoptera found")
return False
else:
print(
f"Found {new_posts_num} new posts from @baleanoptera: updating winners list..."
)
winners[0]["timestamp"] = posts[0]["created"]
for post in posts[:new_posts_num]:
beneficiaries = post["beneficiaries"]
for beneficiary in beneficiaries:
if (
beneficiary["weight"] == 3000
or beneficiary["weight"] == 6000
or beneficiary["weight"] == 6500
):
winner_found = False
for winner in winners:
if winner.get("author", []) == beneficiary["account"]:
winner["wins"] += 1
winner_found = True
break
if not winner_found:
winners.append({"author": beneficiary["account"], "wins": 1})
return winners
def update_winners_list(session: requests.Session):
hall_of_fame = get_contest_winners(session)
if hall_of_fame:
with open("winners.txt", "w", newline="", encoding="utf-8") as file:
for winner in hall_of_fame:
file.write(json.dumps(winner) + "\n")
logger.info("Winners list updated")
E questa è la lista generata, che viene aggiornata ogni volta che lo script viene avviato e rileva un nuovo post di @balaenoptera
{"timestamp": "2024-10-26T00:12:36"}
{"author": "arc7icwolf", "wins": 7}
{"author": "stefano.massari", "wins": 2}
{"author": "bencwarmer", "wins": 4}
{"author": "vittoriozuccala", "wins": 2}
{"author": "lozio71", "wins": 1}
{"author": "p1k4ppa10", "wins": 3}
{"author": "mad-runner", "wins": 1}
{"author": "pousinha", "wins": 2}
{"author": "stewie.wieno", "wins": 4}
{"author": "giuatt07", "wins": 1}
{"author": "tosolini", "wins": 2}
{"author": "li-lou", "wins": 1}
E se voleste curiosare nel codice completo, ho finalmente caricato e condiviso tutto su GitHub!
Trovate la repository completa ed aggiornata qui!
cover realizzata con Bing AI ed editata con GIMP
a supporto della community #OliodiBalena, il 3% delle ricompense di questo post va a @balaenoptera
Se sei arrivato a leggere fin qui, grazie! Se hai voglia di lasciare un upvote, un reblog, un follow, un commento... be', un qualsiasi segnale di vita, in realtà, è molto apprezzato!
Posted Using InLeo Alpha