Claro, os emblemas incluídos são… bons. Não há nada de errado com eles. Mas, e se você quiser mais? E se você quiser ir além do conjunto de símbolos pré-definido? Claro, há uma página de administração onde você pode carregá-los. Mas e se você quiser criar um monte de emblemas?
Bem, boas notícias! Você pode fazer isso através da API. Aqui está um código Python mostrando como funciona. (E ele concede o emblema no final, para garantir.)
Isso deve ser fácil de ler, mesmo que você não seja um programador Python. Você pode até replicá-lo com curl na linha de comando, se quiser.
Isso espera que sua chave de API esteja em uma variável de ambiente DISCOURSE_API_KEY.
#!/usr/bin/python3
import os # Para ler o ambiente
import sys # Para sair. :)
import hashlib # Para o hash da imagem
import requests # Faz todo o trabalho real
# Informações do site e autenticação
DISCOURSE = "discussion.fedoraproject.org"
DISCOURSE_API_USER = "mattdm"
DISCOURSE_API_KEY = os.getenv("DISCOURSE_API_KEY")
if not DISCOURSE_API_KEY:
print(f"Erro: DISCOURSE_API_KEY deve ser definido no ambiente", file=sys.stderr)
sys.exit(2)
# Informações para o seu emblema. Presumivelmente, em uso real você não codificaria isso.
NAME = "Apex"
IMAGE = "apex.png"
DESCRIPTION = "Bênção da FPL"
MORE = "Você é incrível e todos deveriam saber!"
TARGET_USER = "mattdm"
# Nossos cabeçalhos de autenticação, de cima.
HEADERS = {'Api-Key': DISCOURSE_API_KEY, 'Api-Username': DISCOURSE_API_USER}
# A partir disso, você pode obter os IDs e descrições de grupos de emblemas, e
# os vários tipos de emblemas. Se você quiser. Não estou usando isso neste exemplo.
r = requests.get(f"https://{DISCOURSE}/admin/badges.json", headers=HEADERS)
if r.status_code != 200:
print(f"Erro ao obter lista de emblemas: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
# Verifica se o nome já existe.
# Provavelmente há uma maneira melhor de fazer isso, mas será suficiente.
if NAME in list(map(lambda x: x['name'], r.json()['badges'])):
print(f"Erro: o emblema '{NAME}' já existe.")
sys.exit(3)
# Lê a imagem. Você gostaria de um melhor tratamento de erros aqui em código real!
with open(IMAGE, "rb") as f:
image_data = f.read()
# Provavelmente deveria fazer alguma verificação de sanidade no
# tamanho/dimensões do arquivo de imagem bem aqui....
# Mas de qualquer forma, monta um pacote de informações sobre ele para fazer upload.
# A única coisa complicada aqui realmente é obter o checksum da imagem.
file_info = {'file_name': f'{IMAGE}',
'file_size': f'{len(image_data)}',
'type': 'badge_image',
'metadata[sha1-checksum]': hashlib.sha1(image_data).hexdigest(),
}
# E pergunta ao Discourse para onde enviar.
r = requests.post(
f"https://{DISCOURSE}/uploads/generate-presigned-put", json=file_info, headers=HEADERS)
if r.status_code != 200:
print(
f"Erro ao perguntar onde fazer upload da imagem: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
upload_url = r.json()['url']
upload_uid = r.json()['unique_identifier']
# Agora coloque onde nos foi dito para colocar.
r = requests.put(upload_url, data=image_data)
if r.status_code != 200:
print(
f"Erro ao fazer upload da imagem para armazenamento externo: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
# E diga ao Discourse que funcionou, e receba um ID que podemos referenciar mais tarde.
r = requests.post(f"https://{DISCOURSE}/uploads/complete-external-upload",
data=f'unique_identifier={upload_uid}', headers=HEADERS)
if r.status_code != 200:
print(f"Erro ao completar upload: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
image_id = r.json()['id']
# Nota: se você quiser usar font awesome, deixe `image_upload_id` em branco e
# em vez disso, defina `icon` para o nome correspondente do font awesome. E claro
# você pode pular toda a parte de upload de imagem nesse caso!
badge = {'allow_title': 'true',
'multiple_grant': 'false',
'listable': 'true',
'show_posts': 'false',
'target_posts': 'false',
'name': f'{NAME}',
'description': f'{DESCRIPTION}',
'long_description': f'{DESCRIPTION} {MORE}',
'image_upload_id': f'{image_id}',
'badge_grouping_id': '5',
'badge_type_id': '1',
}
r = requests.post(
f"https://{DISCOURSE}/admin/badges.json", json=badge, headers=HEADERS)
if r.status_code != 200:
print(f"Erro ao criar emblema: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
badge_id = r.json()['badge']['id']
print(f'Emblema "{NAME}: {DESCRIPTION}" foi criado como {badge_id}!')
# E para completar, conceda o emblema!
# Você também pode adicionar um "motivo", que deve vincular a um post ou tópico.
bestow = {'username': f"{TARGET_USER}", 'badge_id': f'{badge_id}'}
r = requests.post(f"https://{DISCOURSE}/user_badges",
json=bestow, headers=HEADERS)
if r.status_code != 200:
print(f"Erro ao conceder emblema: obteve {r.status_code}", file=sys.stderr)
sys.exit(1)
print(f'Usuário {TARGET_USER} recebeu o novo emblema!')