LimeSurvey per JSON-RPC ansprechen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
16_Bit
User
Beiträge: 21
Registriert: Donnerstag 26. März 2020, 14:14

Hallo liebe Python-Community,

ich komme leider nur sehr selten zum Programmieren und daher sind meine Python-Kenntnisse sehr rudimentär. Aktuell beiße ich mir an einem kleinen Script die Zähne aus, mit dem ich über die JSON-RPC Schnittstelle User importieren möchte.

Grundlage für mein Script war diese Vorlage.
https://manual.limesurvey.org/RemoteCon ... e_and_glue

Die Methose add_participants wird hier beschrieben.
https://api.limesurvey.org/classes/remo ... rticipants

Ich habe dann diese Funktion erstellt.

Code: Alles auswählen

 # ADD PARTICIPANTS
 def add_participants(sessionkey, surveyID, email, lastname, firstname):
     print (sessionkey, surveyID, email, lastname, firstname)
     # Ausgabe = (u'em3z0iqN8I7A1DMB6Qmn7JEcIXGecxmH', '928126', 'didi.hallervorden@fun.de', 'Hallervorden', 'Didi')
     req = urllib2.Request(url='https://umfrage.bkk-ruv.de/index.php/admin/remotecontrol',\
                           data='{\"method\":\"add_participants\",\"params\":[\"'+sessionkey+'\",\"'+surveyID+'\",\"'+email+'\",\"'+lastname+'\",\"'+firstname+'\"],\"id\":1}')
     req.add_header('content-type', 'application/json')
     req.add_header('connection', 'Keep-Alive')
     try:
         f = urllib2.urlopen(req)
         myretun = f.read()
         j=json.loads(myretun)
         return j['result']
     except :
         e = sys.exc_info()[0]
         print ( "<p>Error: %s</p>" % e )

Das Script läuft durch ohne eine Fehlermeldung, jedoch wird kein User hinzugefügt. Im LimeSurvey Forum kam ich leider nicht weiter. Die Syntax ist zwar so das sich Python nicht daran stört, jedoch könnte das JSON-Format nicht richtig sein, wodurch die Anlage scheitert.

Ich habe zwar nicht die Hoffnung das es hier jemanden gibt der sich mit LimeSurvey auskennt, aber vielleicht reichen Kenntnisse für JSON aus, um mir den entscheidenden Tipp zu geben.

Vorab schon mal vielen Dank das ihr euch mein Problem durchgelesen habt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Fehlerbehandlung ist schonmal falsch, dass jemand selbst exc_info auswertet habe ich noch nie gesehen. Wenn man einen Fehler nicht sinnvoll behandeln kann, sollte man ihn gar nicht behandeln.
Dass Du da json von Hand zusammensetzt ist auch sehr fehlerhaft, weil Sonderzeichen nicht richtig behandelt werden, außerdem ist das unglaublich umständlich.
Benutze am besten das requests-Paket, das kann json von sich aus verarbeiten.
Was soll `myretun` bedeuten? `Tun` heißt Tonne, aber was ist eine retun? Ein my-Prefix macht nur sinn, wenn es auch ein Your gibt.
Ein `connection: Keep-Alive` ist nur sinnvoll, wenn die Verbindung auch tatsächlich irgendwo offen gehalten wird, machst Du aber nicht.

Code: Alles auswählen

UMFRAGE_URL = "https://umfrage.bkk-ruv.de/index.php/admin/remotecontrol"

def add_participants(sessionkey, survey_id, email, lastname, firstname):
     print (sessionkey, survey_id, email, lastname, firstname)
     # Ausgabe = (u'em3z0iqN8I7A1DMB6Qmn7JEcIXGecxmH', '928126', 'didi.hallervorden@fun.de', 'Hallervorden', 'Didi')
     payload = {
        "method": "add_participants",
        "params": [sessionkey, survey_id, email, lastname, firstname],
        "id": 1,
     }
     request = urllib2.Request(UMFRAGE_URL, data=json.dumps(payload))
     request.add_header('Content-Type', 'application/json')
     with urllib2.urlopen(request) as response:
         result = json.load(response)
         return result['result']
Wie genau der Service anzusprechen ist, kann ich aus der Dokumentation jetzt nicht auf die Schnelle herausfinden. Dass hier Parameter als Liste übergeben werden müssen, ist zwar ungewöhnlich und nicht gerade robust, aber wenns sein muß...

Was ist denn der komplette Response?
einfachTobi
User
Beiträge: 491
Registriert: Mittwoch 13. November 2019, 08:38

Ich habe tatsächlich mal LimeSurvey verwendet, allerdings ohne die API zu bemühen.
Zu `urllib3` kann ich nichts sagen, da ich bisher immer `requests` benutzt habe. Versuchs mal so:

Code: Alles auswählen

import requests

URL = "https://myurl/index.php/admin/remotecontrol"
API_USER = "admin"
API_PASSWORD = "password"
SURVEY_ID = 12345

def get_session_key():
    data = {"method": "get_session_key", "params": [API_USER, API_PASSWORD], "id": 1, "plugin": "Authdb"}
    request = requests.get(URL, data=data)
    return request.json()  #  was kommt tatsächlich zurück? wäre zu prüfen und ggf. anzupassen


def add_participants(session_key: str, survey_id: int, email: str, lastname: str, firstname: str):
    user = [{"email": email, "lastname": lastname, "firstname": firstname}]
    params = {"sSessionKey": session_key, "iSurveyID": survey_id, "aParticipantData": user}
    data = {"method": "add_participants", "params": params}
    request = requests.post(URL, data=data)
    return request.json()


if __name__ == "__main__":
    session_key = get_session_key()
    add_user_response = add_participants(session_key, SURVEY_ID, "didi.hallervorden@fun.de", "Hallervorden", "Didi")
Da ich garde keinen LimeSurve-Zugang habe ist das ganze ungetestet. Ich vermute, dass du falsche Variablennamen übermittelt hast.
Benutzeravatar
16_Bit
User
Beiträge: 21
Registriert: Donnerstag 26. März 2020, 14:14

Vielen Dank für eure Antworten. Eure Beiträge haben mich wieder auf den richtigen Pfad gebracht und es funktioniert nun endlich.

Hier ist der Source-Code:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import json
from uuid import uuid4

headers = {'content-type': 'application/json'}
url = "https://URL/index.php/admin/remotecontrol"
apiUser = "lsrc"
apiPassword = "V&v3UV4GJ"
surveyID = 928126

def set_params(method, params):
    data = {'method': method, 'params': params, 'id': str(uuid4())}
    return json.dumps(data)

def get_session_key():
    params = {'username': apiUser, 'password': apiPassword}
    data = set_params('get_session_key', params)
    print(data)
    request = requests.post(url, data=data, headers=headers)
    return request.json()['result']

def add_participants(sessionKey: str, surveyID: int, email: str, lastname: str, firstname: str):
    user = [{"email": email, "lastname": lastname, "firstname": firstname}]
    params = {"sSessionKey": sessionKey, "iSurveyID": surveyID, "aParticipantData": user}
    data = set_params('add_participants', params)
    print(data)
    request = requests.post(url, data=data, headers=headers)
    return request.json()


if __name__ == "__main__":
    sessionKey = get_session_key()
    add_user_response = add_participants(sessionKey, surveyID, "didi.hallervorden@fun.de", "Hallervorden", "Didi")
Antworten