Skip to content

Commit

Permalink
Merge pull request #8 from rwth-acis/releases/1.1.0
Browse files Browse the repository at this point in the history
Releases/1.1.0
  • Loading branch information
AlexanderNeumann authored Jul 11, 2022
2 parents 8670179 + 99e099e commit e2cb145
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker-CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Docker Build and Push

on:
push:
branches: [ master, develop , unnamed-module-fix ]
branches: [ master, develop ]

jobs:
test:
Expand Down
44 changes: 20 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ This service can be used to conduct surveys from LimeSurvey with bots created by

Build
--------

Execute the following command on your shell:

```shell
gradle clean build
gradle build
```

Make sure the ``shs`` database exists. If not, create a new database with the same name
Start
--------

Expand All @@ -22,17 +24,14 @@ bin/start_network.bat
```

Unix/Mac:

```shell
bin/start_network.sh
```




# Starting a survey bot on slack:
# Starting a survey bot on slack

### Creating a slack app

To create a survey chatbot, first a slack app needs to be created. Creating a classic bot app is possible [here](https://api.slack.com/apps?new_classic_app=1). (Wait for the app creation window to pop up, do not click on the green "Create New App" button).
Since the las2peersocial-bot-manager-service uses RTM, a classic app, instead of a new app, is needed.
Expand All @@ -46,30 +45,27 @@ Since the las2peersocial-bot-manager-service uses RTM, a classic app, instead of
- channels:read

- chat:write:bot

- bot

- users:read.email (users:read included)

- incoming-webhook should already be there. If not add under basic information: incoming webhooks: activate incoming webhooks sliding button

- Please do not update scopes!

Now install the app to your wished workspace. After this a token will be generated which is used in the redirect url.

1. Find the bot token: On the left side: OAuth and Permissons, the bot user oauth token (starting with xoxb).

2. Activate interactive components (on the left side: Basic Information: Add features and functionality, Interactive Components. After activating this feature, a Request URL is needed.)

3. Configuring the request url:

- The ip address and port where slack posts the request (the address from the sbfmanager), slack app token, the bot name from the frontend, the instance name from the frontend and the buttonintent text are needed.
http://ipAddress:port/SBFManager/bots/botName/appRequestURL/instanceName/buttonIntent/token.

<http://ipAddress:port/SBFManager/bots/botName/appRequestURL/instanceName/buttonIntent/token>.



### Frontend modeling:
### Frontend modeling

1. Create a bot model by following the guide [here](https://github.com/rwth-acis/Social-Bot-Framework).

Expand All @@ -85,24 +81,24 @@ Now install the app to your wished workspace. After this a token will be generat

- The bot actions needs the following action parameters: (all Content Type: String, Static and Parameter Type: body)

* Name: NameOfUser and Content: the username of your "https://limesurvey.tech4comp.dbis.rwth-aachen.de/" account;
* Name: Password and Content: the password of your limesurvey account;
* Name: surveyID and Content: The surveyID of the survey you want to conduct. You can find this by logging into your limesurvey account and then clicking on "List surveys". In the survey list you will see on the very left side the Survey ID.
* Name: buttonIntent and Content: The button intent, which is going to be recognized when participants click on answer buttons
* Name: sbfmUrl and Content: The URL where the social-bot-framework-manager can receive requests
* Name: slackToken and Content: The slack token that has been added to the "Messenger" with type "Slack" as "Authentication Token"
* Name: adminmail and Content: the email of the admin user (Content Type: String and Parameter Type: body)
- Name: NameOfUser and Content: the username of your "https://limesurvey.tech4comp.dbis.rwth-aachen.de/" account;
- Name: Password and Content: the password of your limesurvey account;
- Name: surveyID and Content: The surveyID of the survey you want to conduct. You can find this by logging into your limesurvey account and then clicking on "List surveys". In the survey list you will see on the very left side the Survey ID.
- Name: buttonIntent and Content: The button intent, which is going to be recognized when participants click on answer buttons
- Name: sbfmUrl and Content: The URL where the social-bot-framework-manager can receive requests
- Name: slackToken and Content: The slack token that has been added to the "Messenger" with type "Slack" as "Authentication Token"
- Name: adminmail and Content: the email of the admin user (Content Type: String and Parameter Type: body)

4. It is possible to add routines for sending reminders or sending results to LimeSurvey.

- for routine: Action Type: Service, Function Name: reminderRoutine.

- for LimeSurvey results: Action Type: Service, Function Name:sendResultsToLimesurvey.

- for MobSOS surveys results: Action Type: Service, Function Name:sendResultsToMobsosSurveys.

- both of them need the action parameters from the main bot actions

### Creating a LimeSurvey Survey:
### Creating a LimeSurvey Survey

-enable under Participants settings: "Allow multiple responses or update responses with one token."
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,115 @@ public Response getTemplate() {
return Response.ok().entity(name).build();
}

@POST
@Path("/surveys")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "REPLACE THIS WITH AN APPROPRIATE FUNCTION NAME", notes = "REPLACE THIS WITH YOUR NOTES TO THE FUNCTION")
@ApiResponses(value = {
@ApiResponse(code = HttpURLConnection.HTTP_OK, message = "REPLACE THIS WITH YOUR OK MESSAGE") })
public Response getSurveys(String input) {
Context.get().monitorEvent(MonitoringEvent.MESSAGE_RECEIVED, input);

JSONObject response = new JSONObject();
JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE);

JSONArray completeReturnJSON = new JSONArray();

try {
JSONObject bodyInput = (JSONObject) p.parse(input);
System.out.println("received message: " + bodyInput);

String url = bodyInput.getAsString("url");
String loginName = bodyInput.getAsString("loginName");
String loginPassword = bodyInput.getAsString("loginPassword");

MiniClient mini = new MiniClient();
mini.setConnectorEndpoint(url);
HashMap<String, String> head = new HashMap<String, String>();

ClientResponse miniClientResponse = mini.sendRequest("POST", url,
("{\"method\": \"get_session_key\", \"params\": [ \"" + loginName + "\", \"" + loginPassword
+ "\"], \"id\": 1}"),
MediaType.APPLICATION_JSON, "", head);
if (miniClientResponse.getHttpCode() != 200) {
System.out.println("Error: " + miniClientResponse.getHttpCode());
return Response.status(miniClientResponse.getHttpCode()).build();

}
JSONObject miniresJSON = (JSONObject) p.parse(miniClientResponse.getResponse());
String sessionKeyString = miniresJSON.getAsString("result");

ClientResponse clientResponseQuestionInfo = mini.sendRequest("POST", url,
("{\"method\": \"list_surveys\", \"params\": [ \"" + sessionKeyString + "\"], \"id\": 1}"),
MediaType.APPLICATION_JSON, "", head);
JSONObject res = (JSONObject) p.parse(clientResponseQuestionInfo.getResponse());
return Response.ok().entity(res.toJSONString()).build();

} catch (Exception e) {
e.printStackTrace();
}

response.put("text", completeReturnJSON);
Context.get().monitorEvent(MonitoringEvent.RESPONSE_SENDING.toString());
return Response.ok().entity(response).build();
}

@POST
@Path("/limeSurveyFunction")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "REPLACE THIS WITH AN APPROPRIATE FUNCTION NAME", notes = "REPLACE THIS WITH YOUR NOTES TO THE FUNCTION")
@ApiResponses(value = {
@ApiResponse(code = HttpURLConnection.HTTP_OK, message = "REPLACE THIS WITH YOUR OK MESSAGE") })
public Response runLimesurveyFunction(String input) {
Context.get().monitorEvent(MonitoringEvent.MESSAGE_RECEIVED, input);

JSONObject response = new JSONObject();
JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE);

JSONArray completeReturnJSON = new JSONArray();

try {
JSONObject bodyInput = (JSONObject) p.parse(input);
System.out.println("received message: " + bodyInput);

String url = bodyInput.getAsString("url");
String loginName = bodyInput.getAsString("loginName");
String loginPassword = bodyInput.getAsString("loginPassword");
String command = bodyInput.getAsString("command");
JSONArray params = (JSONArray) bodyInput.get("params");

MiniClient mini = new MiniClient();
mini.setConnectorEndpoint(url);
HashMap<String, String> head = new HashMap<String, String>();

ClientResponse miniClientResponse = mini.sendRequest("POST", url,
("{\"method\": \"get_session_key\", \"params\": [ \"" + loginName + "\", \"" + loginPassword
+ "\"], \"id\": 1}"),
MediaType.APPLICATION_JSON, "", head);
JSONObject miniresJSON = (JSONObject) p.parse(miniClientResponse.getResponse());
String sessionKeyString = miniresJSON.getAsString("result");
params.add(0, sessionKeyString); // add session key to params

JSONObject request = new JSONObject();
request.put("method", command);
request.put("params", params);
request.put("id", 1);

ClientResponse clientResponseQuestionInfo = mini.sendRequest("POST", url,
(request.toJSONString()),
MediaType.APPLICATION_JSON, "", head);
JSONObject res = (JSONObject) p.parse(clientResponseQuestionInfo.getResponse());
return Response.ok().entity(res.toJSONString()).build();

} catch (Exception e) {
e.printStackTrace();
}

response.put("text", completeReturnJSON);
Context.get().monitorEvent(MonitoringEvent.RESPONSE_SENDING.toString());
return Response.ok().entity(response).build();
}

@POST
@Path("/post/{input}")
@Produces(MediaType.TEXT_PLAIN)
Expand All @@ -282,8 +391,7 @@ public Response postTemplate(@PathParam("input") String myInput) {
}

@POST
@Path("/getLimeSurveyResponses")
@Consumes(MediaType.TEXT_PLAIN)
@Path("/responses")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "Get results from LimeSurvey.",
Expand Down Expand Up @@ -314,6 +422,10 @@ public Response limesurveyConnector(String input) {
String surveyID = bodyInput.getAsString("surveyID");
String documentType = "json";

if (surveyID == null) {
return Response.status(HttpURLConnection.HTTP_BAD_REQUEST).entity("surveyID is null").build();
}

MiniClient mini = new MiniClient();
mini.setConnectorEndpoint(url);
HashMap<String, String> head = new HashMap<String, String>();
Expand All @@ -323,12 +435,25 @@ public Response limesurveyConnector(String input) {
String sessionKeyString = miniresJSON.getAsString("result");

// now get question information, to add to response json object
ClientResponse clientResponseQuestionInfo = mini.sendRequest("POST", url, ("{\"method\": \"list_questions\", \"params\": [ \"" + sessionKeyString + "\", \"" + surveyID + "\"], \"id\": 1}"), MediaType.APPLICATION_JSON, "", head);
ClientResponse clientResponseQuestionInfo = mini
.sendRequest(
"POST", url, ("{\"method\": \"list_questions\", \"params\": [ \"" + sessionKeyString
+ "\", \"" + surveyID + "\"], \"id\": 1}"),
MediaType.APPLICATION_JSON, "", head);

if (clientResponseQuestionInfo.getHttpCode() != 200) {
return Response.status(clientResponseQuestionInfo.getHttpCode())
.entity(clientResponseQuestionInfo.getResponse()).build();
}

JSONObject questionInfoJSON = (JSONObject) p.parse(clientResponseQuestionInfo.getResponse());
String questionInfo = questionInfoJSON.getAsString("result");
JSONArray questionListJSON = (JSONArray) p.parse(questionInfo);

ClientResponse clientResponse = mini.sendRequest("POST", url, ("{\"method\": \"export_responses\", \"params\": [ \"" + sessionKeyString + "\", \"" + surveyID + "\", \"" + documentType + "\"], \"id\": 1}"), MediaType.APPLICATION_JSON, "", head);
ClientResponse clientResponse = mini.sendRequest(
"POST", url, ("{\"method\": \"export_responses\", \"params\": [ \"" + sessionKeyString + "\", \""
+ surveyID + "\", \"" + documentType + "\"], \"id\": 1}"),
MediaType.APPLICATION_JSON, "", head);
JSONObject clientResponseJSON = (JSONObject) p.parse(clientResponse.getResponse());
String encodedFile = clientResponseJSON.getAsString("result");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
package i5.las2peer.services.SurveyHandler;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

import i5.las2peer.api.Context;
import i5.las2peer.api.logging.MonitoringEvent;
import i5.las2peer.services.SurveyHandler.database.SurveyHandlerServiceQueries;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import org.glassfish.jersey.server.JSONP;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -31,13 +18,9 @@
import i5.las2peer.p2p.LocalNodeManager;
import i5.las2peer.security.UserAgentImpl;
import i5.las2peer.testing.MockAgentFactory;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;


/**
Expand Down Expand Up @@ -554,7 +537,8 @@ public void testLimeSurveyConnector() {
client.setConnectorEndpoint(connector.getHttpEndpoint());
client.setLogin(testAgent.getIdentifier(), testPass);

ClientResponse result = client.sendRequest("POST", mainPath + "getLimeSurveyResponses", "{\"loginName\":" + NameOfUser + ",\"url\":" + uri + ",\"surveyID\":" + surveyID + ",\"loginPassword\":" + Password + "}");
ClientResponse result = client.sendRequest("POST", mainPath + "responses", "{\"loginName\":" + NameOfUser
+ ",\"url\":" + uri + ",\"surveyID\":" + surveyID + ",\"loginPassword\":" + Password + "}");
JSONParser p = new JSONParser();
JSONObject resultJSON = (JSONObject) p.parse(result.getResponse());
String resultString = resultJSON.getAsString("text");
Expand Down
1 change: 1 addition & 0 deletions etc/initdb.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
create database shs
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
core.version=1.2.2
service.name=i5.las2peer.services.SurveyHandler
service.class=SurveyHandlerService
service.version=1.0.1
service.version=1.1.0
java.version=17

las2peer_user1.name=alice
Expand Down

0 comments on commit e2cb145

Please sign in to comment.