public static async Task Run( [QueueTrigger("visionscanner")] string tweetQuery, [Table("visiontweet")] CloudTable visionTweetTable, [Queue("visionscanned")] IAsyncCollector <string> visionScannedQueue, TraceWriter log) { log.Info($"VisionScanner processing TweetId: {tweetQuery}"); long tweetId = long.Parse(tweetQuery); long originalTweetId = tweetId; List <string> screenNamesToReplyTo = new List <string>(); var service = Helper.TwitterService(); TwitterStatus tweet = null; TweetEntity tweetEntity = null; while (tweet == null) { //moving this check inside the while loop to stop processing retweets var tweetDetails = Helper.FetchTweetFromStorage(tweetId.ToString()); if (tweetDetails != null) //already processed { log.Info($"VisionScanner Already Processed TweetId: {tweetId}"); return; } tweet = service.GetTweet(new GetTweetOptions { Id = tweetId, IncludeEntities = true, TweetMode = TweetMode.Extended }); //build up mentions list for replyto - will distinct later screenNamesToReplyTo.Add("@" + tweet.User.ScreenName); foreach (var mention in tweet.Entities.Mentions) { screenNamesToReplyTo.Add("@" + mention.ScreenName); } tweetEntity = new TweetEntity(tweet); //no media? try the parent if (!tweet.Entities.Media.Any()) { log.Info($"VisionScanner No media found in TweetId: {tweetQuery}"); // Documentation Link: Add an entity to a table - https://cda.ms/nn visionTweetTable.Execute(TableOperation.Insert(tweetEntity)); if (tweet.InReplyToStatusId == null) { //walked up the whole chain - no media found return; } else { tweetId = ((long)tweet.InReplyToStatusId); tweet = null; } } } var mediaDesc = new MediaDescription(tweet.Id); var photos = tweet.Entities.Media.Where(m => m.MediaType == TwitterMediaType.Photo); foreach (var media in photos) { log.Info($"VisionScanner FetchVisionDescriptionAsync TweetId/MediaId: {tweetQuery}/{media.Id}"); var vision = await Helper.FetchVisionDescriptionAsync(tweet, media); mediaDesc.VisionDescription.Add(media.IdAsString, vision); } tweetEntity.VisionJson = JsonConvert.SerializeObject(mediaDesc); // Documentation Link: Add an entity to a table - https://cda.ms/nn visionTweetTable.Execute(TableOperation.Insert(tweetEntity)); var dto = new TweetScannedDTO { TwitterStatus = tweetEntity.BuildTwitterStatus(), OriginalTweetId = originalTweetId, UsersToReplyTo = screenNamesToReplyTo.Distinct().ToArray(), MediaDescription = mediaDesc }; log.Info($"VisionScanner Queuing VisionScanned TweetId: {tweetQuery}"); await visionScannedQueue.AddAsync(JsonConvert.SerializeObject(dto)); log.Info($"VisionScanner processed TweetId: {tweetQuery}"); }
public static void Run([QueueTrigger("visionscanned")] string tweetEntity, [Table("visiontweet")] CloudTable visionTweetTable, TraceWriter log) { TweetScannedDTO dto = JsonConvert.DeserializeObject <TweetScannedDTO>(tweetEntity); log.Info($"VisionScanned function processing TweetId: {dto.TwitterStatus.Id}"); var service = Helper.TwitterService(); foreach (var vision in dto.MediaDescription.VisionDescription) { var jsonUrl = string.Format(Helper.GetEnvironmentVariable("JsonDetailsUrlFormat"), dto.OriginalTweetId); var confidence = vision.Value.description.captions[0].confidence; string captionPrefix = "Caption"; if (confidence < .2) { captionPrefix = "Guessing"; } else if (confidence < .4) { captionPrefix = "Unsure"; } else if (confidence < .6) { captionPrefix = "Maybe"; } else if (confidence < .8) { captionPrefix = "Probably"; } var replyToNames = string.Join(" ", dto.UsersToReplyTo); var status = $"{replyToNames} Confidence: {confidence,0:P2}" + $"{Environment.NewLine}{Environment.NewLine}" + $"{captionPrefix}: {vision.Value.description.captions[0].text}" + $"{Environment.NewLine}{Environment.NewLine}" + "Tags: {0}" + $"{Environment.NewLine}{Environment.NewLine}" + "Full API Result: {1}"; const int TCO_LENGTH = 22; const int MAX_LENGTH = 230; const int LINE_BREAKS_CHAR_COUNT = 12; //replyToNames are not counted in tweet length var spaceAvailable = MAX_LENGTH - status.Length - TCO_LENGTH - LINE_BREAKS_CHAR_COUNT + replyToNames.Length; var tags = new List <string>(); var tagLength = 0; foreach (var tag in vision.Value.description.tags) { tagLength += tag.Length + 2; //2 is for the ", " when joined if (tagLength > spaceAvailable) { break; } tags.Add(tag); } status = string.Format(status, string.Join(", ", tags), jsonUrl); log.Info($"VisionScanned function Sending Tweet: {dto.TwitterStatus.Id} - {status}"); var options = new SendTweetOptions { Status = status, InReplyToStatusId = dto.OriginalTweetId, TrimUser = false }; var sentStatus = service.SendTweet(options, (tweet, response) => { if (response.StatusCode != HttpStatusCode.OK) { //if a tweet fails to send we log it, in table storage var failedTweet = new FailedTweetEntity(dto.TwitterStatus) { TweetJson = JsonConvert.SerializeObject(response) }; // Documentation Link: Add an entity to a table - https://cda.ms/nn visionTweetTable.Execute(TableOperation.Insert(failedTweet)); log.Error($"VisionScanned Failed to Send TweetId: {dto.TwitterStatus.Id}, Response: {failedTweet.TweetJson}"); throw new Exception(response.StatusCode.ToString()); } }); } log.Info($"VisionScanned function processed TweetId: {dto.TwitterStatus.Id}"); }