Initial commit
This commit is contained in:
commit
1fa320cbd3
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from getpass import getpass
|
||||
from os.path import dirname, expanduser
|
||||
from requests.auth import AuthBase
|
||||
from requests.exceptions import RequestException
|
||||
from sys import exit, stderr
|
||||
import gi
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import requests
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
class Api:
|
||||
class DeviceAuth(AuthBase):
|
||||
def __init__(self, token):
|
||||
self.token = token
|
||||
|
||||
def __call__(self, r):
|
||||
r.headers['Authorization'] = f'Device {self.token}'
|
||||
return r
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
|
||||
def __call__(self, method, endpoint, **kwargs):
|
||||
data = {'params' if method == 'GET' else 'json': kwargs}
|
||||
r = requests.request(method, self.config['url'] + endpoint % self.config, auth=Api.DeviceAuth(self.config['api_token']), **data)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except RequestException as e:
|
||||
print(e, file=stderr)
|
||||
print(r.text, file=stderr)
|
||||
raise e
|
||||
|
||||
if r.headers['content-type'] == 'application/json':
|
||||
return r.json()
|
||||
|
||||
return r.text
|
||||
|
||||
class Window(Gtk.Window):
|
||||
def __init__(self, config):
|
||||
super().__init__(title='Mark as paid')
|
||||
|
||||
self.config = config
|
||||
self.api = Api(config)
|
||||
|
||||
self.entry = Gtk.Entry()
|
||||
self.entry.set_visibility(False)
|
||||
self.entry.set_width_chars(32)
|
||||
self.entry.connect('activate', self.on_entry_activate)
|
||||
self.add(self.entry)
|
||||
|
||||
def info(self, primary_text, secondary_text):
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=self,
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.INFO,
|
||||
buttons=Gtk.ButtonsType.OK,
|
||||
text=primary_text,
|
||||
)
|
||||
dialog.format_secondary_text(secondary_text)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def on_entry_activate(self, widget):
|
||||
results = self.api('GET', '/api/v1/organizers/%(organizer)s/checkinrpc/search/', ignore_status='true', list=self.config['list'], search=widget.get_text())
|
||||
if results['count'] == 0:
|
||||
self.info('Keine Ergebnisse', 'Bitte präzisiere deine Eingabe.')
|
||||
return
|
||||
if results['count'] > 1:
|
||||
self.info('Mehrere Ergebnisse', 'Bitte präzisiere deine Eingabe.')
|
||||
return
|
||||
|
||||
order = self.api('GET', f"/api/v1/organizers/%(organizer)s/events/%(event)s/orders/{results['results'][0]['order']}/")
|
||||
if order['status'] == 'p':
|
||||
self.info('Bereits bezahlt', 'Die Bestellung ist bereits bezahlt.')
|
||||
return
|
||||
if order['status'] == 'e':
|
||||
self.info('Abgelaufen', 'Die Bestellung ist abgelaufen.')
|
||||
return
|
||||
if order['status'] == 'c':
|
||||
self.info('Storniert', 'Die Bestellung wurde storniert.')
|
||||
return
|
||||
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=self,
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.QUESTION,
|
||||
buttons=Gtk.ButtonsType.YES_NO,
|
||||
text=f"Gesamtbetrag: {order['total']}",
|
||||
)
|
||||
dialog.format_secondary_text('Wurde der gesamte Betrag in bar entgegengenommen?')
|
||||
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
if response == Gtk.ResponseType.YES:
|
||||
try:
|
||||
self.api('POST', f"/api/v1/organizers/%(organizer)s/events/%(event)s/orders/{results['results'][0]['order']}/mark_paid/")
|
||||
self.info('Zahlung bestätigt', 'Die Zahlung wurde bestätigt, die Tickets sind nun gültig.')
|
||||
except RequestException:
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=self,
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.ERROR,
|
||||
buttons=Gtk.ButtonsType.OK,
|
||||
text='Fehler',
|
||||
)
|
||||
dialog.format_secondary_text('Ein Fehler ist aufgetreten.')
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
config_path = expanduser('~/.config/pretix-markaspaid/config.json')
|
||||
|
||||
try:
|
||||
with open(config_path) as f:
|
||||
config = json.loads(f.read())
|
||||
except FileNotFoundError:
|
||||
handshake = json.loads(getpass('Please scan initialization qr code... '))
|
||||
if handshake['handshake_version'] != 1:
|
||||
print(f"Unknown handshake version {handshake['handshake_version']}", file=stderr)
|
||||
exit(1)
|
||||
|
||||
r = requests.post(f"{handshake['url']}/api/v1/device/initialize", json={
|
||||
'hardware_brand': platform.system(),
|
||||
'hardware_model': platform.release(),
|
||||
'software_brand': 'mark-as-paid',
|
||||
'software_version': '0.1.0',
|
||||
'token': handshake['token'],
|
||||
})
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except RequestException as e:
|
||||
print(e, file=stderr)
|
||||
print(r.text, file=stderr)
|
||||
exit(1)
|
||||
|
||||
r = r.json()
|
||||
|
||||
config = {
|
||||
'api_token': r['api_token'],
|
||||
'device_id': r['device_id'],
|
||||
'event': input('Event: '),
|
||||
'list': int(input('Check-in list: ')),
|
||||
'organizer': r['organizer'],
|
||||
'unique_serial': r['unique_serial'],
|
||||
'url': handshake['url'],
|
||||
}
|
||||
|
||||
os.makedirs(dirname(config_path))
|
||||
with open(config_path, 'w') as f:
|
||||
f.write(json.dumps(config))
|
||||
|
||||
window = Window(config)
|
||||
window.connect('destroy', Gtk.main_quit)
|
||||
window.show_all()
|
||||
|
||||
Gtk.main()
|
Loading…
Reference in New Issue