a proper project@
This commit is contained in:
commit
bb0474fe07
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
**/__pycache__/
|
||||
.venv/
|
||||
.idea/
|
||||
keys/
|
||||
poetry.lock
|
20
examples/check-key.py
Normal file
20
examples/check-key.py
Normal file
@ -0,0 +1,20 @@
|
||||
import requests
|
||||
|
||||
|
||||
host = 'forum.lunduke.com'
|
||||
username = 'gmgauthier'
|
||||
url = f"https://{host}/posts.json"
|
||||
|
||||
|
||||
with open('../keys/cli_key.txt', 'r') as key:
|
||||
api_key = key.read()
|
||||
api_key = api_key.replace('\n', '').replace('\r', '')
|
||||
|
||||
|
||||
headers={
|
||||
"api_key": api_key,
|
||||
"api_username": username
|
||||
}
|
||||
response = requests.get(url,headers=headers)
|
||||
print(response.status_code)
|
||||
print(response.json())
|
34
examples/example.py
Normal file
34
examples/example.py
Normal file
@ -0,0 +1,34 @@
|
||||
from lunduke.config import DiscourseConfig
|
||||
from lunduke.auth import DiscourseAuth
|
||||
from lunduke.client import DiscourseClient
|
||||
|
||||
|
||||
def main():
|
||||
# Set up configuration
|
||||
config = DiscourseConfig(
|
||||
host='forum.lunduke.com',
|
||||
username='gmgauthier'
|
||||
)
|
||||
|
||||
# Set up authentication
|
||||
auth = DiscourseAuth(
|
||||
api_key_file='../keys/cli_key.txt',
|
||||
username=config.username
|
||||
)
|
||||
|
||||
# Create client
|
||||
client = DiscourseClient(config, auth)
|
||||
|
||||
# Use the client
|
||||
try:
|
||||
response = client.get('/posts.json')
|
||||
posts = response['latest_posts']
|
||||
print(f"Found {len(posts)} posts")
|
||||
for post in posts:
|
||||
print(post['post_type'], post['username'], post['topic_id'])
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
0
lunduke/__init__.py
Normal file
0
lunduke/__init__.py
Normal file
34
lunduke/auth.py
Normal file
34
lunduke/auth.py
Normal file
@ -0,0 +1,34 @@
|
||||
class DiscourseAuth:
|
||||
"""Handles authentication with the Discourse API."""
|
||||
|
||||
def __init__(self, api_key=None, api_key_file=None, username=None):
|
||||
"""
|
||||
Initialize with API key details.
|
||||
|
||||
Args:
|
||||
api_key: The API key as a string
|
||||
api_key_file: Path to file containing the API key
|
||||
username: The API username
|
||||
"""
|
||||
self.username = username
|
||||
self.api_key = None
|
||||
|
||||
if api_key:
|
||||
self.api_key = api_key
|
||||
elif api_key_file:
|
||||
self._load_key_from_file(api_key_file)
|
||||
|
||||
def _load_key_from_file(self, key_file):
|
||||
"""Load API key from file and clean it."""
|
||||
with open(key_file, 'r') as f:
|
||||
self.api_key = f.read().strip().replace('\n', '').replace('\r', '')
|
||||
|
||||
def get_headers(self):
|
||||
"""Return headers for API requests."""
|
||||
if not self.api_key or not self.username:
|
||||
raise ValueError("API key and username must be set")
|
||||
|
||||
return {
|
||||
"api_key": self.api_key,
|
||||
"api_username": self.username
|
||||
}
|
41
lunduke/client.py
Normal file
41
lunduke/client.py
Normal file
@ -0,0 +1,41 @@
|
||||
import json
|
||||
|
||||
import requests
|
||||
from lunduke.config import DiscourseConfig
|
||||
from lunduke.auth import DiscourseAuth
|
||||
|
||||
|
||||
class DiscourseClient:
|
||||
"""Main client for interacting with the Discourse API."""
|
||||
|
||||
def __init__(self, config, auth):
|
||||
"""
|
||||
Initialize with configuration and authentication.
|
||||
|
||||
Args:
|
||||
config: DiscourseConfig instance
|
||||
auth: DiscourseAuth instance
|
||||
"""
|
||||
self.config = config
|
||||
self.auth = auth
|
||||
self.session = requests.Session()
|
||||
|
||||
def get(self, endpoint, params=None) -> dict:
|
||||
"""
|
||||
Make a GET request to the API.
|
||||
|
||||
Args:
|
||||
endpoint: API endpoint (e.g., '/posts.json')
|
||||
params: Optional query parameters
|
||||
|
||||
Returns:
|
||||
Response data as JSON
|
||||
"""
|
||||
url = f"{self.config.get_base_url()}{endpoint}"
|
||||
headers = self.auth.get_headers()
|
||||
|
||||
response = self.session.get(url, headers=headers, params=params)
|
||||
response.raise_for_status() # Raise exception for error status codes
|
||||
return response.json()
|
||||
|
||||
# Add other HTTP methods as needed (post, put, delete)
|
27
lunduke/config.py
Normal file
27
lunduke/config.py
Normal file
@ -0,0 +1,27 @@
|
||||
class DiscourseConfig:
|
||||
"""Configuration settings for the Discourse API client."""
|
||||
|
||||
def __init__(self, host, username=None, config_file=None):
|
||||
"""
|
||||
Initialize configuration with host and optional username.
|
||||
|
||||
Args:
|
||||
host: The Discourse forum host (e.g., 'forum.lunduke.com')
|
||||
username: The API username
|
||||
config_file: Optional path to a config file
|
||||
"""
|
||||
self.host = host
|
||||
self.username = username
|
||||
self.api_url = f"https://{host}"
|
||||
|
||||
if config_file:
|
||||
self._load_from_file(config_file)
|
||||
|
||||
def _load_from_file(self, config_file):
|
||||
"""Load configuration from a file (JSON/YAML)."""
|
||||
# Implementation for loading config from file
|
||||
pass
|
||||
|
||||
def get_base_url(self):
|
||||
"""Return the base URL for API requests."""
|
||||
return self.api_url
|
0
lunduke/endpoints/__init__.py
Normal file
0
lunduke/endpoints/__init__.py
Normal file
0
lunduke/endpoints/posts.py
Normal file
0
lunduke/endpoints/posts.py
Normal file
0
lunduke/endpoints/users.py
Normal file
0
lunduke/endpoints/users.py
Normal file
17
pyproject.toml
Normal file
17
pyproject.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[project]
|
||||
name = "lunduke-cli"
|
||||
version = "0.1.0"
|
||||
description = "An API client for the Lunduke Discourse server"
|
||||
authors = [
|
||||
{name = "Greg Gauthier",email = "gmgauthier@protonmail.com"}
|
||||
]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"requests (>=2.32.3,<3.0.0)"
|
||||
]
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
36
scripts/keycheck.sh
Executable file
36
scripts/keycheck.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env zsh
|
||||
#
|
||||
|
||||
export AUTH_STRING = "QpklK0BfIbAZJogoY+sNAZHhch29o7wq4G4vBlAr3XRh7cAISzsW0cALv/b/vFGykw34CRDL8xJoX5vHZHKSe6ulOP3aQytrQAMlYRsO08Lp2otz0U8j+f3zL09bHQwASvCDJeJtUrg5cupTHkjQZR2x6AOO69b4VVppBhponcnE9wpb5wHB0kK0sBsDQEKN4G3rb/MiTT9/TgOshRo2/g6VZ7jYQt/dxDQnmoecWlPaAG0wVV3VOkRF3ZxxML7jZPDl/tN6PGwSEEWnctqkzmLVOcl/kq+6sLTA/bkoA7y9x6T5W7jjqNaSPA2/r0gBjy7WnCrZ5qDFHO8BTvvaHQ=="
|
||||
|
||||
export INKEY = "-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCz2JQg/0hMaFZR
|
||||
DVm6vobNpgS8bH9nxH0neGE3Tmb3A3vFGgaWnFSoFsQlMu323vXQxfP+PVID4A10
|
||||
HAYihadlc0fdP5LgNTBYkkG2ena4ci9m52cRu/lE0MvFigyQJ2LZGg16F7Elz3I0
|
||||
KmMdcA++Yqb7nLD3otqF6Y4/T/HVaSw8hVSI+RI98haPSo/UDxSBlGw+Hi8XUiwd
|
||||
Qsrbn5BCh1UN+Wb/gUa2NnmGg8oH0jCdEb7JzB+XTXlmhNMQjHUhn6fwBbacNcD4
|
||||
9cQBK9GiJ1Hk5QLbHyWDF8wdFH6WTcQYPBt2kz/MknWEgw0dNGLhmB12YQrXj4mE
|
||||
qFSiatqZAgMBAAECggEAIPkKw3f6WePhO2/+rQHEdkzDXoZn328DYSqtbDXoI86U
|
||||
MSFh5tgXn0+5O3a4cUQUfmfkoY69jC9WWBzRNSAa/jsiCFrhA1FNIVgDS0Dtpkht
|
||||
D2lKmNJFU8wSKA/02LMX6OThZqqUVHHRpuXEkT+b61Rr+AKU4XoOpXGaHlp6ZJ1a
|
||||
MBhUkhGttZ8aHz64p/MtqhCttAFdBPkwkhKlll/ABs9qvnF1fifhm+RBqni0m3Xg
|
||||
6yTmo2JYMX7QnzfXjdxwq5h8DkG9bdWuhTsWQB7AX1M3TJrsHRUWISTTP972V3/F
|
||||
gshj1zfqRWWIEhiGE647PZxy1VdPOF1jASQtD4g2JwKBgQDsH11dbEdSiXtKkiu/
|
||||
ndWrdQhtk8WbFl/nN39rXO7oMQlAKX0W89TY5n+PGZrxDQnlNg5a4jbzOI4QPvud
|
||||
W19fEAUzsYoqb5LjjsYgbAwNdnjZiiv4ox2bt5taO7MCMH9q80GKtaUCH+m1A0bA
|
||||
Y4Z3b4rl6WohqmOGKK6bi+pHZwKBgQDC/Gif+TRF4e9GqQTdba0ZNgArb4enHlVR
|
||||
pLj47aIFg6vrf5D4U74+4Sf8BOhw6yIybnamEFHd2deECqrYizFxTKufkzAvV+Ux
|
||||
Z3ehuXjFgCg9qSJW2FP3R9Ew5Lthmz/P5uKVR2AhoR2auhaNgw4rnzoAxGjqvRyZ
|
||||
5RiJnTaN/wKBgHU7FUW+7qJB896QN/xIxr77uhV9WoynTTIk0bRiTZMmVWtvrdVp
|
||||
dfHCbu6DTfQD/ze34OSqj5GuMIpMWuxDY1R1Rb/mk6yB/LHSPvf17P36JgILoc0u
|
||||
XxLi09S28ydRINHeuFm/2Y72fTgLymLWhvphfNqtSq4wRH1lUVuU2dpdAoGAMTgD
|
||||
tPXz4vwAKUb66mYH/sgpzM0PYfj/MmexJWzerCOrnvuJfZWt/TNao3wdrHs+G5rU
|
||||
qmCOOcEGbNdAfv7L0Ty4ScSesiSuvwTOJu2pdbk+7ymleGSM9WuUe5IRVrcYqYMv
|
||||
iN0GgBaqYWc90CTXy90aiB0MGsz3zkUNJ5eesMMCgYBuWT8Dqcm7EilaaRjwZkny
|
||||
UENTDIsovLtJpZyhfXgMmGeYwAdJ8RldOM7KwL/jhVWgKTaZa68rhmp2/+q7Rb0M
|
||||
YZiE9JdCUlXWOuQ7g7lynMEgWV7ctt6pDibUCaxgvel7UugbhqpM/UYW1RxC6caC
|
||||
ZOGCjowKexE+WdZqwm0elQ==
|
||||
-----END PRIVATE KEY-----"
|
||||
|
||||
echo "${AUTH_STRING}" | openssl enc -d -a | openssl pkeyutl -decrypt -inkey "${INKEY}" | cat
|
||||
|
Loading…
Reference in New Issue
Block a user