initial commit

This commit is contained in:
muppeth 2023-11-05 14:12:28 +01:00
parent dc52922587
commit c85485f8f3
Signed by: muppeth
GPG Key ID: 0EBC7B9848D04031
3 changed files with 280 additions and 0 deletions

View File

@ -1,2 +1,12 @@
# cstate-pusher
Simple script to send status notifications to CSTATE, XMPP and Fediverse. Script requires slixmpp python package and perhaps other that aren't included by default (note: need to check what is needed to be loaded and either list it or create requirenments file)
To configure, you need to add example.conf to `~/.config/cstate-pusher.conf` and fill in needed credentials. If you use pleroma/akkoma there is no straight forward way to obtain token. Follow those steps:
`curl -s -S -i -X POST -F client_name="Cstate pusher" -F redirect_uris="urn:ietf:wg:oauth:2.0:oob" -F scopes="read write" https://social.example.com/api/v1/apps`
This will give you response with `client_id and` `client_secret`.
Now run this:
`curl -s -S -i -X POST -F client_id="<client_id>" -F client_secret="<secret>" redirect_uri="urn:ietf:wg:oauth:2.0:oob" -F scope="read,write" -F grant_type="password" -F username="<account_username>" -F password="<account_password>" https://social.example.com/oauth/token`
Copy `access_token` to your `cstate-pusher.conf` file under `[Fedi][token]` section.

14
config.ini Normal file
View File

@ -0,0 +1,14 @@
[Fedi]
fediurl = 'http://social.example.com'
token = changeme
[XMPP]
userjid = 'usee@example.com'
nickname = 'User'
password = 'changeme'
roomjid = 'test@chat.example.com'
[GIT]
repo_path = "/path/to/your/local/repository"

256
cstate-pusher.py Executable file
View File

@ -0,0 +1,256 @@
# Simple script to send status information to cstate, xmpp and fediverse
#Load libs
import questionary
from datetime import datetime
import asyncio
import time
import requests
import slixmpp
import os
import configparser
import signal
import sys
import git
from getpass import getpass
# Load configuration from the file
home = os.path.expanduser("~")
config_file = os.path.join(home, ".config", "cstate-pusher.conf")
config = configparser.ConfigParser()
config.read(config_file)
tempalte = "default"
post_tpl = "default"
ftitle = ""
fdate = ""
### Wizard
def multiline_input(prompt_message):
print(prompt_message)
result = []
while True:
line = input()
if line == "" and (len(result) == 0 or result[-1] == ""):
break
result.append(line)
return "\n ".join(result)
def generate_questions(informational):
default_title = "Maintenance window" if informational else "Issue -"
now = datetime.now()
default_time = "21:00" if informational else now.strftime('%H:%M')
current_date = datetime.now().strftime('%Y-%m-%d')
questions = [
{
'type': 'input',
'name': 'title',
'message': 'Enter the title:',
'default': default_title
},
{
'type': 'input',
'name': 'time',
'message': 'Enter the time (HH:MM):',
'default': default_time
},
{
'type': 'input',
'name': 'date',
'message': 'Enter the date (YYYY-MM-DD):',
'default': current_date
},
{
'type': 'confirm',
'name': 'pin',
'message': 'Do you want to pin it?',
'default': True
}
]
if informational:
questions.append(
{
'type': 'checkbox',
'name': 'service_list',
'message': 'Choose services',
'choices': ['Email Server - (IMAP/POP3/SMTP)', 'Webmail (https://webmail.disroot.org)', 'Nextcloud - (https://cloud.disroot.org)', 'XMPP Chat Server - (XMPP)', 'XMPP Webchat - (https://webchat.disroot.org)', 'Etherpad (https://pad.disroot.org)', 'PrivateBin - (https://bin.disroot.org)', 'Lufi - (https://upload.disroot.org)', 'SearX - (https://search.disroot.org)', 'Jitsi - (https://calls.disroot.org)', 'Forgejo - (https://git.disroot.org)', 'Mumble - (https://mumble.disroot.org)', 'Cryptpad - (https://cryptpad.disroot.org)', 'Akkoma - (https://fe.disroot.org)', 'LibreTranslate - (https://translate.disroot.org)']
}
)
else:
questions.extend([
{
'type': 'list',
'name': 'severity',
'message': 'Choose an option:',
'choices': [
"down",
"disrupted",
"notice"
],
},
{
'type': 'checkbox',
'name': 'service_list',
'message': 'Choose services',
'choices': ['Calls', 'Mail', 'Server', 'Webmail', 'Cloud', 'XMPP Chat server', 'XMPP Webchat', 'Pad', 'Bin', 'Upload', 'Searx', 'Git', 'Cryptpad', 'User Password management', 'Disroot.org', 'Website', 'Files', 'Gallery', 'Calendar', 'Contacts', 'Tasks', 'Notes', 'Talk', 'Bookmarks', 'Circles', 'Deck', 'Cospend', 'Forms', 'Appointments']
},
{
'type': 'input',
'name': 'content',
'message': 'Add your content:',
},
])
return questions
def launch_wizard():
global post_tpl, template, ftitle, fdate
informational = questionary.confirm("Is it a Maintenance entry?").ask()
questions = generate_questions(informational)
answers = questionary.prompt(questions)
ftitle = answers['title']
fdate = answers['date']
date_obj = datetime.strptime(fdate, '%Y-%m-%d')
day = date_obj.strftime('%A')
if informational:
services = "".join([f" - {service}\n" for service in answers['service_list']])
template = f"""---
title: 🔧 {answers['title']} 🔧
date: {answers['date']} {answers['time']}:00
informational: {informational}
section: issue
pin: {answers['pin']}
---
On {day} starting from {answers['time']} CET we are going to do some maintenance work. We will make sure to keep as minimal downtime as possible. Following services will not be affected by this migration:
{services}
"""
post_tpl = f"""🔧️ {answers['title']} 🔧️
On {day} starting from {answers['time']} CET we are going to do some maintenance work. We will make sure to keep as minimal downtime as possible. Following services will not be affected by this migration:
{services}
_.~"~._.~"~._.~"~._.~"~.__.~"~._.~"~._.~"~._.~"~.__.~"~._.~"~._.~"~.__
"""
else:
services = "".join([f" - {service}\n" for service in answers['service_list']])
template = f"""---
title: 🔥 {answers['title']} 🔥
date: {answers['date']} {answers['time']}:00
informational: {informational}
section: issue
severity: {answers['severity']}
resolved: False
pin: {answers['pin']}
affected:
{services}
---
{answers['content']}
"""
post_tpl = f"""🔥️ {answers['title']} 🔥️
date: {answers['date']} {answers['time']}:00
{answers['content']}
_.~"~._.~"~._.~"~._.~"~.__.~"~._.~"~._.~"~._.~"~.__.~"~._.~"~._.~"~._.~"~._
"""
print(template)
is_correct = questionary.confirm("Is the information correct?").ask()
if not is_correct:
launch_wizard()
launch_wizard()
### POST to FEDIVERSE
# Define the instance URL and user credentials
instance_url = config['Fedi']['fediurl']
username = config['Fedi']['username']
password = config['Fedi']['password']
token = config['Fedi']['token']
headers = {
'Authorization': f'Bearer {token}',
}
data = {
"status": post_tpl
}
# Print the request details for inspection
print(f"FEDI - Sending a POST request to: {instance_url}")
try:
response = requests.post(f"{instance_url}/api/v1/statuses", headers=headers, data=data, verify=False)
print("FEDI - Message successfully posted.")
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
### POST to XMPP
# Get XMPP credentials from the user
jid = config['XMPP']['userjid']
password = config['XMPP']['password']
room = config['XMPP']['roomjid']
nickname = config['XMPP']['nickname']
message = post_tpl
class MUCBot(slixmpp.ClientXMPP):
def __init__(self, jid, password, room, nickname, message):
slixmpp.ClientXMPP.__init__(self, jid, password)
self.room = room
self.nick = nickname
self.msg = message
self.add_event_handler("session_start", self.start)
self.add_event_handler("muc::%s::got_online" % self.room, self.muc_online)
async def start(self, event):
self.send_presence()
await self.get_roster()
self.plugin['xep_0045'].join_muc(self.room, self.nick)
def muc_online(self, presence):
if presence['muc']['nick'] != self.nick:
self.send_message(mto=self.room, mbody=self.msg, mtype='groupchat')
self.disconnect()
# Create an instance of the XMPP client and connect to the XMPP server
xmpp = MUCBot(jid, password, room, nickname, message)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0045') # Load the MUC plugin
xmpp.register_plugin('xep_0199') # XMPP Ping
xmpp.connect()
xmpp.process(forever=False)
# Run the event loop until the XMPP client is disconnected
print("XMPP - Message sent and disconnected.")
### POST to GIT
# Set the path to your local repository
repo_path = config['GIT']['repo_path']
ftitle = ftitle.replace(" ", "-")
# Modify the template file
print("GIT - Saving to file")
file_path = f"{repo_path}/{fdate}-{ftitle}.md"
with open(file_path, "w") as file:
file.write(template)
# Initialize the repository and add the file
repo = git.Repo(repo_path)
repo.git.add(file_path)
# Commit the changes
print("GIT - Commit to the repo")
commit_message = f"Added a {ftitle}"
repo.index.commit(commit_message)
# Push the changes to the branch
print("GIT - Push to the repo")
origin = repo.remote(name='origin')
origin.push()
# Exit the program
sys.exit()