1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . IO ;
3
4
using System . Linq ;
4
5
using System . Threading . Tasks ;
6
+ using Azure ;
7
+ using Azure . Storage . Blobs . Models ;
8
+ using Azure . Storage . Blobs . Specialized ;
9
+ using Azure . Storage . Sas ;
5
10
using ContentReactor . Audio . Services . Models . Responses ;
6
11
using ContentReactor . Audio . Services . Models . Results ;
7
12
using ContentReactor . Shared ;
8
- using ContentReactor . Shared . BlobRepository ;
13
+ using ContentReactor . Shared . BlobHelper ;
9
14
using ContentReactor . Shared . EventSchemas . Audio ;
10
- using Microsoft . WindowsAzure . Storage . Blob ;
11
15
12
16
namespace ContentReactor . Audio . Services
13
17
{
@@ -23,7 +27,7 @@ public interface IAudioService
23
27
24
28
public class AudioService : IAudioService
25
29
{
26
- protected IBlobRepository BlobRepository ;
30
+ protected BlobHelper BlobHelper ;
27
31
protected IAudioTranscriptionService AudioTranscriptionService ;
28
32
protected IEventGridPublisherService EventGridPublisherService ;
29
33
@@ -32,53 +36,52 @@ public class AudioService : IAudioService
32
36
protected internal const string CategoryIdMetadataName = "categoryId" ;
33
37
protected internal const string UserIdMetadataName = "userId" ;
34
38
protected internal const int TranscriptPreviewLength = 100 ;
35
-
36
- public AudioService ( IBlobRepository blobRepository , IAudioTranscriptionService audioTranscriptionService , IEventGridPublisherService eventGridPublisherService )
39
+
40
+ public AudioService ( BlobHelper blobHelper , IAudioTranscriptionService audioTranscriptionService , IEventGridPublisherService eventGridPublisherService )
37
41
{
38
- BlobRepository = blobRepository ;
42
+ BlobHelper = blobHelper ;
39
43
AudioTranscriptionService = audioTranscriptionService ;
40
44
EventGridPublisherService = eventGridPublisherService ;
41
45
}
42
46
43
47
public ( string id , string url ) BeginAddAudioNote ( string userId )
44
48
{
45
49
// generate an ID for this image note
46
- var audioId = Guid . NewGuid ( ) . ToString ( ) ;
50
+ string audioId = Guid . NewGuid ( ) . ToString ( ) ;
47
51
48
52
// create a blob placeholder (which will not have any contents yet)
49
- var blob = BlobRepository . CreatePlaceholderBlob ( AudioBlobContainerName , userId , audioId ) ;
53
+ BlockBlobClient blob = BlobHelper . GetBlobClient ( AudioBlobContainerName , audioId ) ;
50
54
51
- // get a SAS token to allow the client to write the blob
52
- var writePolicy = new SharedAccessBlobPolicy
53
- {
54
- SharedAccessStartTime = DateTime . UtcNow . AddMinutes ( - 5 ) , // to allow for clock skew
55
- SharedAccessExpiryTime = DateTime . UtcNow . AddHours ( 24 ) ,
56
- Permissions = SharedAccessBlobPermissions . Create | SharedAccessBlobPermissions . Write
57
- } ;
58
- var url = BlobRepository . GetSasTokenForBlob ( blob , writePolicy ) ;
59
55
60
- return ( audioId , url ) ;
56
+ string urlAndSas = BlobHelper . GetSasUriForBlob ( blob , BlobSasPermissions . Create | BlobSasPermissions . Write ) ;
57
+
58
+ return ( audioId , urlAndSas ) ;
61
59
}
62
60
63
61
public async Task < CompleteAddAudioNoteResult > CompleteAddAudioNoteAsync ( string audioId , string userId , string categoryId )
64
62
{
65
- var imageBlob = await BlobRepository . GetBlobAsync ( AudioBlobContainerName , userId , audioId , true ) ;
66
- if ( imageBlob == null || ! await BlobRepository . BlobExistsAsync ( imageBlob ) )
63
+ BlockBlobClient imageBlob = BlobHelper . GetBlobClient ( AudioBlobContainerName , audioId ) ;
64
+ if ( imageBlob == null || ! await imageBlob . ExistsAsync ( ) )
67
65
{
68
66
// the blob hasn't actually been uploaded yet, so we can't process it
69
67
return CompleteAddAudioNoteResult . AudioNotUploaded ;
70
68
}
71
-
69
+
72
70
// if the blob already contains metadata then that means it has already been added
73
- if ( imageBlob . Metadata . ContainsKey ( CategoryIdMetadataName ) )
71
+ Response < BlobProperties > response = await imageBlob . GetPropertiesAsync ( ) ;
72
+ if ( response . Value . Metadata . ContainsKey ( CategoryIdMetadataName ) )
74
73
{
75
74
return CompleteAddAudioNoteResult . AudioAlreadyCreated ;
76
75
}
77
76
78
77
// set the blob metadata
79
- imageBlob . Metadata . Add ( CategoryIdMetadataName , categoryId ) ;
80
- imageBlob . Metadata . Add ( UserIdMetadataName , userId ) ;
81
- await BlobRepository . UpdateBlobMetadataAsync ( imageBlob ) ;
78
+ var metadata = new Dictionary < string , string >
79
+ {
80
+ { CategoryIdMetadataName , categoryId } ,
81
+ { UserIdMetadataName , userId }
82
+ } ;
83
+
84
+ await imageBlob . SetMetadataAsync ( metadata ) ;
82
85
83
86
// publish an event into the Event Grid topic
84
87
var subject = $ "{ userId } /{ audioId } ";
@@ -90,39 +93,33 @@ public async Task<CompleteAddAudioNoteResult> CompleteAddAudioNoteAsync(string a
90
93
public async Task < AudioNoteDetails > GetAudioNoteAsync ( string id , string userId )
91
94
{
92
95
// get the blob, if it exists
93
- var audioBlob = await BlobRepository . GetBlobAsync ( AudioBlobContainerName , userId , id , true ) ;
96
+ BlockBlobClient audioBlob = BlobHelper . GetBlobClient ( AudioBlobContainerName , id ) ;
94
97
if ( audioBlob == null )
95
98
{
96
99
return null ;
97
100
}
98
101
99
- // get a SAS token for the blob
100
- var readPolicy = new SharedAccessBlobPolicy
101
- {
102
- SharedAccessStartTime = DateTime . UtcNow . AddMinutes ( - 5 ) , // to allow for clock skew
103
- SharedAccessExpiryTime = DateTime . UtcNow . AddHours ( 24 ) ,
104
- Permissions = SharedAccessBlobPermissions . Read
105
- } ;
106
- var audioUrl = BlobRepository . GetSasTokenForBlob ( audioBlob , readPolicy ) ;
102
+ string audioUrlAndSas = BlobHelper . GetSasUriForBlob ( audioBlob , BlobSasPermissions . Read ) ;
107
103
108
104
// get the transcript out of the blob metadata
109
- audioBlob . Metadata . TryGetValue ( TranscriptMetadataName , out var transcript ) ;
110
-
111
- return new AudioNoteDetails
105
+ Response < BlobProperties > response = await audioBlob . GetPropertiesAsync ( ) ;
106
+ response . Value . Metadata . TryGetValue ( TranscriptMetadataName , out var transcript ) ;
107
+
108
+ return new AudioNoteDetails
112
109
{
113
- Id = id ,
114
- AudioUrl = audioUrl ,
110
+ Id = id ,
111
+ AudioUrl = audioUrlAndSas ,
115
112
Transcript = transcript
116
113
} ;
117
114
}
118
115
119
116
public async Task < AudioNoteSummaries > ListAudioNotesAsync ( string userId )
120
117
{
121
- var blobs = await BlobRepository . ListBlobsInFolderAsync ( AudioBlobContainerName , userId ) ;
118
+ IList < BlobItem > blobs = await BlobHelper . ListBlobsAsync ( AudioBlobContainerName ) ;
122
119
var blobSummaries = blobs
123
120
. Select ( b => new AudioNoteSummary
124
121
{
125
- Id = b . Name . Split ( '/' ) [ 1 ] ,
122
+ Id = b . Name . Split ( '/' ) [ 1 ] ,
126
123
Preview = b . Metadata . ContainsKey ( TranscriptMetadataName ) ? b . Metadata [ TranscriptMetadataName ] . Truncate ( TranscriptPreviewLength ) : string . Empty
127
124
} )
128
125
. ToList ( ) ;
@@ -136,7 +133,8 @@ public async Task<AudioNoteSummaries> ListAudioNotesAsync(string userId)
136
133
public async Task DeleteAudioNoteAsync ( string id , string userId )
137
134
{
138
135
// delete the blog
139
- await BlobRepository . DeleteBlobAsync ( AudioBlobContainerName , userId , id ) ;
136
+ BlockBlobClient blob = BlobHelper . GetBlobClient ( AudioBlobContainerName , id ) ;
137
+ await blob . DeleteIfExistsAsync ( DeleteSnapshotsOption . IncludeSnapshots ) ;
140
138
141
139
// fire an event into the Event Grid topic
142
140
var subject = $ "{ userId } /{ id } ";
@@ -146,7 +144,7 @@ public async Task DeleteAudioNoteAsync(string id, string userId)
146
144
public async Task < string > UpdateAudioTranscriptAsync ( string id , string userId )
147
145
{
148
146
// get the blob
149
- var audioBlob = await BlobRepository . GetBlobAsync ( AudioBlobContainerName , userId , id , true ) ;
147
+ BlockBlobClient audioBlob = BlobHelper . GetBlobClient ( AudioBlobContainerName , id ) ;
150
148
if ( audioBlob == null )
151
149
{
152
150
return null ;
@@ -156,18 +154,21 @@ public async Task<string> UpdateAudioTranscriptAsync(string id, string userId)
156
154
string transcript ;
157
155
using ( var audioBlobStream = new MemoryStream ( ) )
158
156
{
159
- await BlobRepository . DownloadBlobAsync ( audioBlob , audioBlobStream ) ;
157
+ await audioBlob . DownloadToAsync ( audioBlobStream ) ;
160
158
161
159
// send to Cognitive Services and get back a transcript
162
160
transcript = await AudioTranscriptionService . GetAudioTranscriptFromCognitiveServicesAsync ( audioBlobStream ) ;
163
161
}
164
-
162
+
165
163
// update the blob's metadata
166
- audioBlob . Metadata [ TranscriptMetadataName ] = transcript ;
167
- await BlobRepository . UpdateBlobMetadataAsync ( audioBlob ) ;
164
+ var metadata = new Dictionary < string , string >
165
+ {
166
+ { TranscriptMetadataName , transcript }
167
+ } ;
168
168
169
+ await audioBlob . SetMetadataAsync ( metadata ) ;
169
170
// create a preview form of the transcript
170
- var transcriptPreview = transcript . Truncate ( TranscriptPreviewLength ) ;
171
+ string transcriptPreview = transcript . Truncate ( TranscriptPreviewLength ) ;
171
172
172
173
// fire an event into the Event Grid topic
173
174
var subject = $ "{ userId } /{ id } ";
0 commit comments