Backup dos posts da rede Hive e Steemit para markdown
Disclaimer for those who don't speak Portuguese: I will soon post a more complete Portuguese/English post discussing ways to use the script.
É vamos ver se o Spamminator não vai atrapalhar o alcance do post já que sempre é bom ler as dicas e críticas de outras pessoas sobre um código aberto. Apesar, de, no fim, o código estar em GPL, portanto, é só irem ao Github que vai conter todas estas ferramentas e mandar o bom e velho PR.
Mas, como eu falei a uns dias atrás eu havia voltado a estudar um pouco a API aqui da rede Hive para retornar os backups dos meus posts já que eu pretendo voltar a fazer o backup/mirror do meu conteúdo no meu blog.
Sei que é muito difícil a rede aqui cair mas ... aquilo né. Sempre é bom manter o conteúdo na nossa mão caso o projeto deixe de existir.
E para isto eu criei um script que faz diversas coisas interessantes. Ele baixa os posts aqui da rede Hive e também as imagens nestes posts para o disco local e cria um post pronto para ser usado no Hugo ( com o tempo pretendo colocar também a função para o Jekyll ).
Ele no momento é uma linha de comando e facilita muito a inseri-lo em um cronjob na sua máquina ou VPS. No meu caso ele roda aqui em um servidor na minha rede, baixa o conteúdo e outro job cria o post e o PULL REQUEST no repositório do meu blog no Github.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from beem import Hive
from beem.account import Account
import os
import io
import argparse
import requests
import uuid
from urllib.parse import urlparse
import re
from datetime import datetime, timedelta
def download_image(image_url, path):
try:
# Fazer o download da imagem
response = requests.get(image_url)
if response.status_code == 200:
# Extrair a extensão do arquivo
parsed_url = urlparse(image_url)
_, ext = os.path.splitext(parsed_url.path)
# Gerar um nome de arquivo único com UUID
unique_filename = f"{uuid.uuid4()}{ext}"
file_path = os.path.join(path, unique_filename)
# Salvar a imagem no disco
with open(file_path, 'wb') as f:
f.write(response.content)
print(f"Imagem baixada e salva como: {file_path}")
return unique_filename
else:
print(f"Erro ao baixar a imagem: {image_url} (Status Code: {response.status_code})")
return None
except Exception as e:
print(f"Erro ao processar a imagem {image_url}: {e}")
return None
def extract_images_from_markdown(markdown_content):
# Procurar por imagens no formato ![alt](image_url)
image_urls = re.findall(r'!\[.*?\]\((.*?)\)', markdown_content)
return image_urls
def main(author, path, last=False, include_actifit=False, all_posts=False, today=False, platform="hive"):
# Escolher a blockchain com base na plataforma
if platform == "hive":
node_url = "https://api.hive.blog"
else: # steemit
node_url = "https://api.steemit.com"
# Conectar à blockchain Hive ou Steemit
hive = Hive(node=node_url)
account = Account(author, blockchain_instance=hive)
# Data de ontem e hoje
yesterday = (datetime.utcnow() - timedelta(days=1)).date()
today_date = datetime.utcnow().date()
# Obter os posts da conta
posts = account.get_blog(limit=500) # Ajuste o limite conforme necessário
if last:
# Pega o último post apenas
posts = [posts[0]] if posts else []
# Processar cada post
for post in posts:
if post["author"] != author:
continue
# Verificar se a tag 'actifit' está no post
if 'actifit' in post.get('json_metadata', {}).get('tags', []):
if not include_actifit:
print(f"Post ignorado devido à tag 'actifit': {post['title']}")
continue
# Usar o campo created diretamente como datetime
post_date = post["created"].date()
# Condicionais para --all, --today e posts de ontem
if not all_posts:
if today:
if post_date != today_date:
continue
else:
if post_date != yesterday:
continue
markdown_content = post['body']
title = post['title']
permlink = post['permlink']
link_for_post = f'https://{platform}.blog/@{author}/{permlink}'
# Baixar imagens e substituir os links no markdown
images = post.get('json_metadata', {}).get('image', [])
if images:
print(f"Imagens encontradas no post (json_metadata): {images}")
# Extrair imagens do markdown
markdown_images = extract_images_from_markdown(markdown_content)
if markdown_images:
print(f"Imagens encontradas no markdown: {markdown_images}")
# Baixar todas as imagens encontradas no json_metadata e no markdown
all_images = images + markdown_images
for image_url in all_images:
downloaded_image_name = download_image(image_url, path)
if downloaded_image_name:
markdown_content = markdown_content.replace(image_url, downloaded_image_name)
post_final = f'---\n<br />**Postado originalmente na rede {platform.capitalize()}: [{link_for_post}]({link_for_post})** <br />\n----'
yaml_prefix = '---\n'
TitleYaml = title.replace(':', '').replace('\'', '').replace('#', '').replace('(', '').replace(')', '')
# Construir o prefixo YAML
yaml_prefix += f'title: {TitleYaml}\n'
yaml_prefix += f'date: {post["created"]}\n'
yaml_prefix += f'permlink: /{platform}/{permlink}\n'
yaml_prefix += 'type: posts\n'
yaml_prefix += f'categories: ["{platform.capitalize()}"]\n'
yaml_prefix += f'author: {author}\n---\n'
# Nome do arquivo
filename = os.path.join(path, f"{post_date}_{permlink}.md")
# Salvar o conteúdo em um arquivo Markdown
with io.open(filename, "w", encoding="utf-8") as f:
f.write(yaml_prefix + markdown_content + post_final)
print(f"Post salvo: {filename}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("author", help="Nome da conta na Hive ou Steemit")
parser.add_argument("path", help="Caminho onde os arquivos Markdown serão salvos")
parser.add_argument("--last", action="store_true", help="Pega o último post somente")
parser.add_argument("--actifit", action="store_true", help="Inclui posts com a tag 'actifit'")
parser.add_argument("--all", action="store_true", help="Pega todos os posts, ignorando o filtro de data")
parser.add_argument("--today", action="store_true", help="Pega apenas os posts de hoje")
parser.add_argument("--steemit", action="store_true", help="Usar a rede Steemit em vez da Hive")
args = parser.parse_args()
# Definir a plataforma (Hive ou Steemit)
platform = "steemit" if args.steemit else "hive"
main(args.author, args.path, args.last, args.actifit, args.all, args.today, platform)
A idéia disto surgiu porque por mais que a rede esteja distribuída ainda dependemos de pontos centrais para que tenhamos acesso ao conteúdo. E assim, dependendo do que ocorrer principalmente em um país como o nosso em que alguns juízes se acham semideuses.
O processo é bem simples. O script vai na API da rede Hive, busca todos os posts de um usuário específicio e manda o conteúdo markdown dos nossos posts aqui para um diretório.
Como vira e mexe também fazemos a inserção de imagens, este script pega a imagem, efetua o download da mesma para o disco local e reescreve o endereço da imagem no markdown para apontar para o disco local.
Isto é bom pois o meu script anterior não fazia isto e, este processo eu tinha que efetuar manualmente. E imagine isto para diversos posts em uma semana. Como eu era muito mais ativo aqui isto atrapalhava um pouco.
Mas espero que esta primeira versão já ajude. Tenho algumas idéias para o próximo passo, que seria ele baixar o post e também inserir as tags no cabeçalho do post do Hugo.
E lógico, em breve, também criar o esquema para que ele consiga gerar arquivos para o Jekyll ( apesar de, caso necessário, a pessoa possa usar os scripts do próprio Jekyll para migrar o post para o formato que ele utiliza ).
Uso do script
O uso do script é muito fácil. Aqui deixo inclusive alguns exemplos de como podemos utilizá-lo no dia a dia.
Temos alguns parâmetros que foram inseridos no script:
--last
- este parâmetro pega somente o último post--actifit
. - pega todos os posts incluindo aqueles que tenham a tag actifit. Por padrão o script não pega estes posts e inclui no backup.--all
pega todo os posts. Por padrão o script pega somente os posts de ontem--steemit
quando este parâmetro é inserido ele passa a baixar os posts da rede Steemit ( breve pretendo colocar as outras redes irmãs também )
Exemplos de uso:
Para pegar todos os posts:
venv/bin/python hive_posts_yesterday_to_md.py ataliba hive --all
Para pegar apenas os posts de hoje:
venv/bin/python hive_posts_yesterday_to_md.py ataliba hive --today
Para pegar todos os posts, incluindo os com actifit
:
venv/bin/python hive_posts_yesterday_to_md.py ataliba hive --all --actifit
Para pegar somente o último post de hoje:
venv/bin/python hive_posts_yesterday_to_md.py ataliba hive --last --today
Imagem direto do Pixabay
Obrigado por promover a Língua Portuguesa em suas postagens.
Vamos seguir fortalecendo a comunidade lusófona dentro da Hive.