Song Import über die REST-Api
-
Hallo,
Tatsächlich habe ich mir jetzt gerade die gleiche Frage gestellt.
Ich habe eine XML Datei mit unserem Lieder-Fundus, die ich gerne automatisch in CT importieren würde.In der alten API hab ich noch eine Funktion zum anlegen, löschen und editieren gefunden, aber die neue API sehe ich diese Funktionen noch ebenfalls nicht.
Ist das zeitnah geplant anzubieten?
Gruß Micha -
Könnt ihr bitte eine grobe Einschätzung geben, wann Song importieren / editieren von der API unterstützt werden wird?
Das Thema wird bei mir doch recht zeitnah relevant werden, sodass ich da gerne eine Einschätzung hätte.Kann ich auf einen automatisierten Workflow hinarbeiten oder muss ich mir definitiv eine Alternative suchen, da das Thema in den kommenden Monaten noch nicht angefasst wird?
Gruß Micha
-
Alle Funktionen die es aktuell im CT Frontend gibt werden über Apis genutzt.
Also gibt es auch eine Api für die Songs.Nur gibt es dafür noch keine neue Api dafür.
Hier noch die Doku zur Api. Die alte Api ist die AJAX API.
-
Hallo zusammen,
müsste man nicht in der REST API über den Files Endpoint/files/{domainType}/{domainIdentifier}
als POST neue Dateien hochladen können, bzw. mit DELETE auch entfernen? Als DomainType hätte ich hier "Song_Arrangement" erwartet.
Wenn ich das ganz konkret ausprobiere, also z.B.
curl -X 'POST' \ 'https://elkw1610.krz.tools/api/files/song_arrangement/394' \ -H 'accept: application/json' \ -H 'Content-Type: multipart/form-data' \ -F 'files=@20220513_203630.jpg;type=image/jpeg'
bekomme ich jedoch einen Fehler
{ "message": "There are validation errors", "messageKey": "validation.error", "translatedMessage": "Die eingegebenen Daten waren nicht korrekt.", "args": [], "errors": [ { "fieldId": "files", "message": "Nur eine Datei darf für diesen Domain Typ hochgeladen werden.", "messageKey": "validation.domainfiles", "args": { "name": "files", "value": {} } } ] }
Außerdem stellt sich die Frage in wie weit immer ALLE Attachments eines Song_Arragements gelöscht werden oder auch durch gezieltes löschen und neu hoch landen ein entpsprechender Sync möglich wäre ...
Langsam frage ich mich ob die API überhaupt schon im bisher dokumentierten Teil funktioniert ...
Also für das Beispiel kurz zum Kontext ...
Ich habe einen test song mit 3 arrangements angelegt, das 3. hat noch keine Datei und die ID 394, die anderen 385 und 383. Der Song selber hat entpsrechend die ID 383
Vom Handy aus versuche ich angemeldet ein neues attachement hoch zu laden. (Über die Swagger Demo auf /api) wird angezeigt als curl Parameter "song_arrangement" und der domainIdentifier "394" ist darin auch zu erkennen.
-
@ben-ste Die Fehlermeldung ist hier etwas irreführend.
Problem ist aber, dass der Parameter
files[]
heißen muss und nichtfile
.
Damit sollte es funktionieren.Also in deinem Beispiel dann:
curl -X 'POST' \ 'https://elkw1610.krz.tools/api/files/song_arrangement/394' \ -H 'accept: application/json' \ -H 'Content-Type: multipart/form-data' \ -F 'files[]=@20220513_203630.jpg;type=image/jpeg'
-
@davidschilling
Hallo David,
das kann ich leider auf die schnelle so nicht prüfen - wie gesagt probiert hatte ich es mit der offiziellen Interaktiven Swagger Doku der REST API - kann das sein das das Attribut dann da falsch drin steht wenn du sagst das es auf die [] ankommt?Normal würde ich die REST API kurz in RESTED probieren, nur kann ich da nicht so schnell mal eine Datei einbauen ...
-
Hi @davidschilling
ich habe es mittlerweile mit folgendem Python Code probiert ...
Die Verbindung ist via token in der Session gespeichert (und mit /whoami getestet)headers = { 'Content-Type': 'multipart/form-data', 'accept': 'application/json', 'CSRF-Token': csrf_token } url = domain + '/api/files/{}/{}'.format(domain_type, domain_identifier) file = open('test.pdf', 'rb') data = {'files[]': file} response = session.post(url=url, headers=headers, data=data)
Der Fehler bleibt der gleiche
{"message":"There are validation errors","messageKey":"validation.error","translatedMessage":"Die eingegebenen Daten waren nicht korrekt.","args":[],"errors":[{"fieldId":"files","message":"Nur eine Datei darf f\\u00fcr diesen Domain Typ hochgeladen werden.","messageKey":"validation.domainfiles","args":{"name":"files","value":null}}]}
Alternativ habe ich auch mit files statt files[] (als Key) und mit file als [] als Attribut in dem Data Dict probiert sogar im post request "files=" statt "data=" probiert
Sorry beim besten willen - irgendwie ist die API an der Stelle etwas sagen wir mal "ungünstig" dokumentiert.
Kann das sein, dass hier ein Array mit allen Parametern für einen File erwartet wird statt nur einer einzigen Datei? Das würde auch erklären warum je ID, obwohl es mehrere Files geben kann, jeweils nur ein Aufruf möglich ist. Wie zuvor geschrieben klingt das ja fast danach als das beim löschen alle Dateien mit dem Identifier entfernt werden.
Falls du Zeit hättest das gemeinsam weiter zu verfolgen könnte man ja anschließend die REST-API Doku ggf. etwas erweitern damit nicht noch andere in das selbe Problem laufen.Ergänzung - ich habe in der Zwischenzeit einen anderen DomainType (GroupImage) probiert und stoße auf das gleiche Problem
-
Ich hab es gerade nochmal getestet. Genau dieser curl Aufruf funktioniert bei mir:
curl -X POST http://churchtools.test/api/files/avatar/1 -H 'cookie: ChurchTools_template=nmtncfh5kushiqp9ikidn27n66' -H 'content-type: multipart/form-data' -F 'files[]=@/Users/david/Downloads/8BS_6600.JPG;type=image/jpeg' -H 'csrf-token: db639402f593da794d99aa2706339314da62a7c0dbcc3bb8c505d82d6702b73e'
Es müssen natürlich Cookie, Url und CSRF Token angepasst werden.
Auch mit dem DomainType
song_arrangement
habe ich es erfolgreich getestet. -
Hallo @davidschilling ,
nach etwas probieren bekomme ich es zumindest über CURL jetzt hin und glaube dir endlich das die API auch funktioniert Mal gucken ob man diese komische Absurdität mit den [] im Parameter auch in Python umsetzen kann.
Interessant war noch das zuerst der Login via Token nicht funktioniert hatte.Gemäß deinem Beispiel konnte ich aber aus dem LocalStorage von Firefox zum testen meinen Cookie extrahieren ...curl -X POST https://elkw1610.krz.tools/api/files/song_arrangement/394 \ -H 'cookie: ChurchTools_ct_elkw1610=GEHEIM' \ -H 'content-type: multipart/form-data' \ -F 'files[]=@media/pinguin.png;type=image/png'
Hatte dann sogar auch ohne CSRF das entsprechende Ergebnis gebracht.
Nach 2 oder 3 weiteren Versuchen klappte es dann auch mit Authorization statt Cookie (wohl wissend, dass ich damit immer neue Logins im Log erzeuge ...)curl -X POST https://elkw1610.krz.tools/api/files/song_arrangement/394 \ -H 'Authorization: Login GEHEIM' \ -H 'content-type: multipart/form-data' \ -F 'files[]=@media/pinguin2.png;type=image/png'
Über ein GET konnte ich übrigens undokumentiert über das selbe Schema an die URL der Dateien
curl -X GET https://elkw1610.krz.tools/api/files/song_arrangement/394 \ -H 'Authorization: Login GEHEIM' \ -H 'content-type: multipart/form-data'
da war dann u.a. der Link der dann die Datei enthält.
Also Zusammengefasst ... Wenn ich SongArrangements Updaten will muss ich erst alle Dateien herunterladen, meine neue Datei im Download überschreiben / ergänzen und anschließend alle wieder hoch laden.
Danke für die Hilfestellung - bin mal gespannt wann wann die API noch einmal erweitert wird. Jetzt ist ja der Finder endlich fertig ...
-
Hallo zusammen, da sicher noch andere auf das Problem stoßen werden ...
Der komische "files[]" Parameter und die fehlende Angabe des entsprechend zu übergebenden Formats in der API führen sowohl in der API Demo als auch bei Verwendung des Python Requests Modul zu Problemen.WICHTIG - was in der Doku fehlt ist, dass nicht das FileObjekt sondern ein Tuple aus Dateiname und Fileobjekt erwartet wird, ansonsten gibt der Fehler entweder Code 200 ohne etwas durchzuführen, oder Code 500 bei falschen Objekten zurück.
@davidschilling - Vielleicht könntet ihr das in der Doku ergänzen und Swagger so ausführen, dass auch das Beispiel funktioniert ... Ich glaube die Try Funktion geht genau deswegen nicht ...Für alle die es mit Python nutzen wollen unten der getestete Code ... Wichtig - zuerst die Session über einen GET Aufruf auf /api/whoami mit entsprechenden Authorization Token initiieren.
@davidschilling - auch dafür wäre ein Beispiel in der Doku gut - das der Text Login vor dem Token stehen bleiben soll und es sich um einen normalen Header statt einer richtigen Auth Methode handelt war zumindest für mich nicht von Anfang an klar.def upload_file(session,file_to_upload, domain_type='song_arrangement', domain_identifier=394): """ Helper function to upload an attachment to any module of ChurchTools :param session: which is allready Authorized :param file_to_upload: open file object - e.g. open('media/pinguin.png', 'rb') :param domain_type: The domain type. Currently supported are 'avatar', 'groupimage', 'logo', 'attatchments', 'html_template', 'service', 'song_arrangement', 'importtable', 'person', 'familyavatar', 'wiki_.?'. :param domain_identifier: ID of the object in ChurchTools :return: """ url = domain + '/api/files/{}/{}'.format(domain_type, domain_identifier) # add files as files form data with dict using 'files[]' as key and (tuple of filename and fileobject) files = {'files[]': (file_to_upload.name, file_to_upload)} response = session.post(url=url, files=files) """ # Issues with HEADERS in Request module when using non standard 'files[]' key in POST Request # Workaround for ChurchTools - generate session with /api/whoami GET request and reuse it # Requests module usually automatically completes required header Params e.g. Content-Type ... # in case manual header e.g. for AUTH is used, headers don't auto complete # and server rejects messsages or data is ommited # Error Code 500 is also missing in API documentation headers = {'Authorization': 'Login GEHEIM'} response_test = requests.post(url=url, headers=headers, files=files) #> this fails ! """ if response.status_code == 200: response_content = json.loads(response.content) logging.info(response_content) else: logging.warning(response.content.decode())
-
Ich hatte auch Probeme mit dem Endpunkt und einer Implementierung in PHP. Über die Bibliothek Guzzle habe ich es leider überhaupt nicht zum Laufen bekommen, weil Guzzle die Kombination aus dem Header "Content-type:multipart/form-data" und der Option "form_params" aussschließt.
Mit einem selbst zusammengebauten Curl-Request funktioniert es jetzt allerdings:
$ch = curl_init("https://intern.church.tools/api/files/avatar/21?login_token=" . $loginToken); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "content-type:multipart/form-data", "csrf-token:" . $csrfToken ]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, ["files[]" => curl_file_create($filePath)]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $resultString = (string)curl_exec($ch); $curlInfo = curl_getinfo($ch);
Ich habe das ganze auch in einen API-Wrapper verpackt. (https://github.com/5pm-HDH/churchtools-api)
Wer also auch via PHP Datein hochladen möchte kann auch die den Wrapper benutzen:$newFile = (new FileRequestBuilder("avatar", 22))->upload(__DIR__ . "/avatar-1.png");
-
@davidschilling, @ben-ste: Ich habe exakt so wie ihr versucht Avatar-Bilder für unsere Mitglieder hochzuladen und komme nicht über folgende Meldung hinaus:
{'message': 'There are validation errors', 'messageKey': 'validation.error', 'translatedMessage': 'Die eingegebenen Daten waren nicht korrekt.', 'args': [], 'errors': [{'fieldId': 'files', 'message': 'Nur eine Datei darf für diesen Domain Typ hochgeladen werden.', 'messageKey': 'validation.domainfiles', 'args': {'input': None, 'multipleAllowed': True}}]}
@ben-ste: Funktioniert dein Codebeispiel immer noch und gibt es vielleicht etwas, was du im Codeschnipsel nicht dokumentiert hast, was ich übersehen könnte?
Habe mittlerweile alle möglichen Kombinationen aus Header, Files und Data durch und bekomme es nicht hin Dateien hochzuladen. -
@richard , mein Code findet sich mittlerweile unter https://github.com/bensteUEM/ChurchToolsAPI/releases/tag/1.2.3.10
inkl automatischen Tests. Der Dateiupload für Song arrangenents geht auf jeden Fall, ich meine ein Testfall lädt auch ein Gruppensymbol, bin mir aber nicht sicher
Ich würde also davon ausgehen, dass es grundsätzlich geht, ggf haben sich aber in der Zwischenzeit weitere Prämissen aufgetan die dort im Code auch sauber dokumentiert sind (u.a. CSRF Token usw die dort mit Login Automatische abgehandelt werden)Meine Empfehlung wäre daher wie auf der release Seite beschrieben das Paket via pip zu installieren und dann entsprechend der Doku zu verwenden. Solltest du dabei auf ungetestete oder reproduzierbar defekte Anwendungsfälle stoßen kann ich es gerne dort in die Wunschliste aufnehmen.
-