Skip to content

Commit

Permalink
Merge pull request #1388 from OfficeDev/v-pakoshti/botfileuploadAndOt…
Browse files Browse the repository at this point in the history
…herSamplesFixes

Fixed issues for these samples
  • Loading branch information
Pawank-MSFT authored Sep 16, 2024
2 parents eff5f68 + 4660b26 commit 1390b1a
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -51,6 +53,8 @@ public class TeamsFileUploadBot extends TeamsActivityHandler {

private static String microsoftAppId;
private static String microsoftAppPassword;
private static final String FILES_DIR = "files";
private TurnContext context;

public TeamsFileUploadBot(Configuration configuration) {
microsoftAppId = configuration.getProperty("MicrosoftAppId");
Expand Down Expand Up @@ -190,51 +194,71 @@ private boolean messageWithDownload(Activity activity) {
return messageWithFileDownloadInfo;
}

private CompletableFuture<ResultPair<String>> upload(
FileConsentCardResponse fileConsentCardResponse
) {

private CompletableFuture<ResultPair<String>> upload(FileConsentCardResponse fileConsentCardResponse) {
AtomicReference<ResultPair<String>> result = new AtomicReference<>();

return CompletableFuture.runAsync(() -> {
Map<String, String> context = (Map<String, String>) fileConsentCardResponse
.getContext();
Map<String, String> context = (Map<String, String>) fileConsentCardResponse.getContext();
File filePath = new File("files", context.get("filename"));
HttpURLConnection connection = null;

try {
URL url = new URL(fileConsentCardResponse.getUploadInfo().getUploadUrl());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Length", Long.toString(filePath.length()));
connection.setRequestProperty(
"Content-Range",
String.format("bytes 0-%d/%d", filePath.length() - 1, filePath.length())
);

try (
FileInputStream fileStream = new FileInputStream(filePath);
OutputStream uploadStream = connection.getOutputStream()
) {
byte[] buffer = new byte[4096];
int bytes_read;
while ((bytes_read = fileStream.read(buffer)) != -1) {
uploadStream.write(buffer, 0, bytes_read);

try {
URI uri = new URI(fileConsentCardResponse.getUploadInfo().getUploadUrl());
URL url = uri.toURL();
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "image/png");
connection.setRequestProperty("Content-Length", Long.toString(filePath.length()));
connection.setRequestProperty(
"Content-Range",
String.format("bytes 0-%d/%d", filePath.length() - 1, filePath.length())
);

try (FileInputStream fileStream = new FileInputStream(filePath);
OutputStream uploadStream = connection.getOutputStream()) {

byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileStream.read(buffer)) != -1) {
uploadStream.write(buffer, 0, bytesRead);
}
}
}

result.set(new ResultPair<String>(true, null));
} catch (Throwable t) {
result.set(new ResultPair<String>(false, t.getLocalizedMessage()));
} finally {
if (connection != null) {
connection.disconnect();
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
result.set(new ResultPair<>(true, null));

} else {
result.set(new ResultPair<>(false, "Failed with HTTP error code: " + responseCode));

Thread.sleep(1000); // Simple backoff before retrying
}
} catch (IOException e) {
result.set(new ResultPair<>(false, "IOException: " + e.getMessage()));

} catch (URISyntaxException e) {
result.set(new ResultPair<>(false, "URISyntaxException: " + e.getMessage()));

} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupt status
result.set(new ResultPair<>(false, "InterruptedException: " + e.getMessage()));

} finally {
if (connection != null) {
connection.disconnect();
}
}
}
})
.thenApply(aVoid -> result.get());

}).thenApply(aVoid -> result.get());
}



private CompletableFuture<Void> processInlineImage(TurnContext turnContext) {
Attachment attachment = turnContext.getActivity().getAttachments().get(0);
final HttpURLConnection[] connection = {null};
Expand All @@ -243,7 +267,8 @@ private CompletableFuture<Void> processInlineImage(TurnContext turnContext) {
try {
// Save the inline image to Files directory.
String filePath = "files/imageFromUser.png";
URL url = new URL(attachment.getContentUrl());
URI uri = new URI(attachment.getContentUrl());
URL url = uri.toURL();
connection[0] = (HttpURLConnection) url.openConnection();
connection[0].setRequestProperty("Authorization", "Bearer " + token);
try (
Expand Down Expand Up @@ -302,7 +327,8 @@ private CompletableFuture<ResultPair<String>> downloadAttachment(Attachment atta
HttpURLConnection connection = null;

try {
URL url = new URL(fileDownload.getDownloadUrl());
URI uri = new URI(fileDownload.getDownloadUrl());
URL url = uri.toURL();
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);

Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion samples/msgext-expert-finder-js/assets/sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"source": "officeDev",
"title": "Expert Finder with SSO in Copilot using multi parameter search",
"shortDescription": "Microsoft Teams message extension that can be used as a plugin to Search for candidates and share profiles matching a criteria.",
"url": "https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/msgext-expert-finder",
"url": "https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/msgext-expert-finder-js",
"longDescription": [
"This sample implements a Teams message extension that can be used as a plugin for Microsoft Copilot for Microsoft 365. The message extension allows users to query the candidates based on their skills, location and availability."
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
<head>
<link rel="stylesheet" type="text/css" href="/static/styles/msteams-16.css"/>
<link rel="stylesheet" type="text/css" href="/static/styles/custom.css"/>
<script src="https://res.cdn.office.net/teams-js/2.0.0/js/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
<script src="https://res.cdn.office.net/teams-js/2.27.0/js/MicrosoftTeams.min.js"
integrity="sha384-QGb/h0ACuraFEnqrpkMcMBTU+baTLZy1Mh61IGbM206IPGRWiWCIL5dkLzG1RKZH"
crossorigin="anonymous"></script>
<script>
microsoftTeams.app.initialize().then(() => {
});
// Method to start a new conversation.
function startConversation() {
microsoftTeams.app.getContext().then((context) => {
console.log(context);
microsoftTeams.conversations.openConversation(
{
"subEntityId": Date.now(),
"subEntityId": Date.now().toString(),
"entityId": context.page.id,
"channelId": context.channel.id,
"title": "Task Title",
Expand All @@ -40,6 +41,7 @@
}
// Method to continue an existing conversation.
function continueConversation() {
microsoftTeams.app.getContext().then((context) => {
microsoftTeams.conversations.openConversation(
Expand All @@ -51,8 +53,11 @@
"conversationId": localStorage.conversationId
}
);
});
})
}
// Method to execute deeplink to redirect to the subentity/conversation in the channel.
function deeplinkConversation() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
</link>
<link rel="stylesheet" type="text/css" href="/static/styles/custom.css">
</link>
<script src="https://res.cdn.office.net/teams-js/2.0.0/js/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
<script src="https://res.cdn.office.net/teams-js/2.26.0/js/MicrosoftTeams.min.js"
integrity="sha384-gqPg5qCjdUgTGRZ/stLskrnJllL5h5+f4kTqvxVqtl2FdT7PVRa9Q7zq4gFlZ7bO"
crossorigin="anonymous"></script>
<script>
microsoftTeams.app.initialize().then(() => {
});
Expand All @@ -16,7 +18,7 @@
microsoftTeams.app.getContext().then((context) => {
microsoftTeams.conversations.openConversation(
{
"subEntityId": Date.now(),
"subEntityId": Date.now().toString(),
"entityId": context.page.id,
"channelId": context.channel.id,
"title": "Task Title",
Expand All @@ -29,10 +31,11 @@
// Callback function for open conversation.
// We should save the subEntityId and conversationId to continue an existing conversartion
function onStartConversation(conversationResponse) {
localStorage.setItem("subEntityId", conversationResponse.subEntityId);
localStorage.setItem("conversationId", conversationResponse.conversationId);
localStorage.setItem("subEntityId", conversationResponse.subEntityId);
localStorage.setItem("conversationId", conversationResponse.conversationId);
}


// Method to close an existing conversation.
function closeConversation() {
microsoftTeams.conversations.closeConversation();
Expand All @@ -56,7 +59,7 @@
// Method to execute deeplink to redirect to the subentity/conversation in the channel.
function deeplinkConversation() {
microsoftTeams.app.getContext().then((context) => {
microsoftTeams.app.openLink("https://teams.microsoft.com/l/message/"+context.channel.id+"/" + localStorage.conversationId + "?groupId="+context.team.groupId+"&tenantId="+context.user.tenant.id+"&parentMessageId="+localStorage.conversationId);
microsoftTeams.app.openLink("https://teams.microsoft.com/l/message/" + context.channel.id + "/" + localStorage.conversationId + "?groupId=" + context.team.groupId + "&tenantId=" + context.user.tenant.id + "&parentMessageId=" + localStorage.conversationId);
})
}
</script>
Expand All @@ -76,22 +79,26 @@
<tr>
<td>Start Conversation</td>
<td>To open a conversation</td>
<td><img src="../../images/start-conversation.svg" onclick="startConversation()" title="Click to start a new conversation"/></td>
<td><img src="../../images/start-conversation.svg" onclick="startConversation()"
title="Click to start a new conversation" /></td>
</tr>
<tr>
<td>Close Conversation</td>
<td>To close the conversation view</td>
<td><img src="../../images/close.svg"onclick="closeConversation()" title="Click to close the conversation view"/></td>
<td><img src="../../images/close.svg" onclick="closeConversation()"
title="Click to close the conversation view" /></td>
</tr>
<tr>
<td>Continue Conversation</td>
<td>To continue a conversation.</td>
<td><img src="../../images/continue-conversation.svg" onclick="continueConversation()" title="Click to continue existing conversation"/></td>
<td><img src="../../images/continue-conversation.svg" onclick="continueConversation()"
title="Click to continue existing conversation" /></td>
</tr>
<tr>
<td>Deeplink to conversation</td>
<td>Redirect to channel conversation.</td>
<td><img src="../../images/link.svg" onclick="deeplinkConversation()" title="Click to redirect to conversation in chat"/></td>
<td><img src="../../images/link.svg" onclick="deeplinkConversation()"
title="Click to redirect to conversation in chat" /></td>
</tr>
</table>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
let productName;
let image = "";
// Method to scan barcode
//Method to scan barcode
function scanBarCode() {
var config = {
timeOutIntervalInSec: 30
Expand Down Expand Up @@ -67,24 +67,37 @@
}, config);
}
// Method to capture product image
function captureImage() {
//Method to capture product image
function selectMedia() {
microsoftTeams.app.initialize().then(() => {
var imageProp = {
sources: [microsoftTeams.media.Source.Camera, microsoftTeams.media.Source.Gallery],
startMode: microsoftTeams.media.CameraStartMode.Photo,
ink: false,
cameraSwitcher: false,
textSticker: false,
enableFilter: true
};
// Method to ask for image capture permission and then capture image
microsoftTeams.media.captureImage((error, files) => {
// If there's any error, an alert shows the error message/code
var mediaInput = {
mediaType: microsoftTeams.media.MediaType.Image,
maxMediaCount: 1,
imageProps: imageProp
};
microsoftTeams.media.selectMedia(mediaInput, function (error, attachments) {
if (error) {
if (error.message) {
alert(" ErrorCode: " + error.errorCode + error.message);
} else {
alert(" ErrorCode: " + error.errorCode);
}
} else if (files) {
image = files[0].content;
$("#productImg").attr("src", "data:image/png;base64," + image);
$("#productStatus").show();
}
} else if (attachments) {
image = attachments[0];
$("#productImg").attr("src", "data:image/png;base64," + image.preview);
$("#productStatus").show();
}
});
});
}
Expand All @@ -93,7 +106,7 @@
var productStatus = status ? "Approved" : "Rejected";
const formData = new FormData();
formData.append('productId', productId);
formData.append('image', "data:image/png;base64," + image);
formData.append('image', "data:image/png;base64," + image.preview);
formData.append('status', productStatus);
$("#productStatus").hide();
$("#captureImage").hide();
Expand Down Expand Up @@ -125,7 +138,7 @@
<div class="surface">
<div class="panel">
<div id="captureImage">
<button type="button" class="btn btn-outline-info" onclick="captureImage()">Capture Image</button>
<button type="button" class="btn btn-outline-info" onclick="selectMedia()">Capture Image</button>
</div>
<div id="productStatus">
<label id="scannedText"></label>
Expand Down

0 comments on commit 1390b1a

Please sign in to comment.