public async Task Profile([Summary("username", "The username of the Instagram account.")] string username) { // Check whitelist: if (!Whitelist.IsServerOnList(((Context.Guild == null) ? (0) : (Context.Guild.Id)))) { // Self-hosted whitelist notification for official bot: if (Context.Client.CurrentUser.Id == 815695225678463017) { await RespondAsync("This bot is now self-host only. Learn more about this change in the updates channel on the support server: https://discord.gg/8dkjmGSbYE", ephemeral : true); } else { await RespondAsync("This guild is not on the whitelist. The command was blocked.", ephemeral : true); } return; } //Buy more time to process posts: await DeferAsync(false); // Get IG account: InstagramProcessor instagram = new InstagramProcessor(InstagramProcessor.AccountFinder.GetIGAccount()); //Create url: string url = username; if (!Uri.IsWellFormedUriString(username, UriKind.Absolute)) { url = "https://instagram.com/" + username; } // Process profile: InstagramProcessorResponse response = await instagram.PostRouter(url, (int)Context.Guild.PremiumTier, 1); // Check for failed post: if (!response.success) { await FollowupAsync(response.error); return; } // If not a profile for some reason, treat otherwise: if (!response.onlyAccountData) { await FollowupAsync("This doesnt appear to be a profile. Try using `/link` for posts."); return; } IGEmbedBuilder embed = new IGEmbedBuilder(response, Context.User.Username); IGComponentBuilder component = new IGComponentBuilder(response, Context.User.Id); await FollowupAsync(embed : embed.AutoSelector(), allowedMentions : AllowedMentions.None, components : component.AutoSelector()); }
public async Task ProfileParser([Remainder] string args = null) { // Check whitelist: if (!Whitelist.IsServerOnList(Context.Guild.Id)) { // Ignore if not on list: return; } using (Context.Channel.EnterTypingState()) { // Get IG account: InstagramProcessor instagram = new InstagramProcessor(InstagramProcessor.AccountFinder.GetIGAccount()); string url = "https://instagram.com/" + args.Replace(" ", "/"); // Process profile: InstagramProcessorResponse response = await instagram.PostRouter(url, (int)Context.Guild.PremiumTier, 1); // Check for failed post: if (!response.success) { await Context.Message.ReplyAsync(response.error); return; } // If not a profile for some reason, treat otherwise: if (!response.onlyAccountData) { await Responder(url, Context); return; } IGEmbedBuilder embed = new IGEmbedBuilder(response, Context.User.Username); IGComponentBuilder component = new IGComponentBuilder(response, Context.User.Id); await Context.Message.ReplyAsync(embed : embed.AutoSelector(), allowedMentions : AllowedMentions.None, components : component.AutoSelector()); //Attempt to remove any automatic embeds: DiscordTools.SuppressEmbeds(Context); } }
public async Task Link(string url, [Summary(description: "The post number for the desired post in a carousel.")][MinValue(1)] int index = 1, [Summary(description: "Set to true to mark the image/video and caption as a spoiler.")] bool HasSpoilers = false) { // Check whitelist: if (!Whitelist.IsServerOnList(((Context.Guild == null) ? (0) : (Context.Guild.Id)))) { // Self-hosted whitelist notification for official bot: if (Context.Client.CurrentUser.Id == 815695225678463017) { await RespondAsync("This bot is now self-host only. Learn more about this change in the updates channel on the support server: https://discord.gg/8dkjmGSbYE", ephemeral : true); } else { await RespondAsync("This guild is not on the whitelist. The command was blocked.", ephemeral : true); } return; } //Buy more time to process posts: await DeferAsync(false); // Get IG account: InstagramProcessor instagram = new InstagramProcessor(InstagramProcessor.AccountFinder.GetIGAccount()); //Process Post: InstagramProcessorResponse response = await instagram.PostRouter(url, Context.Guild, index); if (!response.success) { //Failed to process post: await FollowupAsync(response.error, ephemeral : true); return; } //Create embed builder: IGEmbedBuilder embed = new IGEmbedBuilder(response, Context.User.Username, HasSpoilers); //Create component builder: IGComponentBuilder component = new IGComponentBuilder(response, Context.User.Id); if (response.isVideo) { if (response.stream != null) { //Response with stream: using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.mp4", "An Instagram Video.", isSpoiler: HasSpoilers); await Context.Interaction.FollowupWithFileAsync(attachment, embed : embed.AutoSelector(), components : component.AutoSelector()); } } else { //Response without stream: await FollowupAsync(response.contentURL.ToString(), embed : embed.AutoSelector(), components : component.AutoSelector()); } } else { if (response.stream != null) { using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.jpg", "An Instagram Image.", isSpoiler: HasSpoilers); await Context.Interaction.FollowupWithFileAsync(attachment, embed : embed.AutoSelector(), allowedMentions : AllowedMentions.None, components : component.AutoSelector()); } } else { await FollowupAsync(embed : embed.AutoSelector(), components : component.AutoSelector()); } } }
/// <summary> /// Gets the latests posts for all subscriptions /// </summary> /// <returns></returns> public async Task GetLatestsPosts() { //Ensure module is enabled. if (!ModuleEnabled) { Console.WriteLine("Module disabled."); return; } if (InSubLoop) { //Prevents multiple loops running at once which could cause an instagram block. Console.WriteLine("Already in loop. Skipping."); return; } else { InSubLoop = true; } try { //Unsubscribe oversubs: await UnsubscribeOverSubscriptions(); Console.WriteLine("Getting new posts!"); var getdbfeed = await FollowedAccountsContainer.Find(_ => true).ToListAsync(); //Randomize the order of the IG accounts: Random rand = new Random(); getdbfeed.OrderBy(item => rand.Next()); foreach (var dbfeed in getdbfeed) { Console.WriteLine("Checking " + dbfeed.InstagramID); try { // Get IG account: InstagramProcessor instagram = new InstagramProcessor(InstagramProcessor.AccountFinder.GetIGAccount()); //Check to see if there is any channel that is subscribed to IG accounts: if (dbfeed.SubscribedChannels.Count == 0) { //If not, delete. await this.FollowedAccountsContainer.DeleteOneAsync(x => x.InstagramID == dbfeed.InstagramID); } else //Otherwise proceed: { //Set last check as now: dbfeed.LastCheckTime = DateTime.Now; var newIGPosts = await instagram.PostsSinceDate(long.Parse(dbfeed.InstagramID), dbfeed.LastPostDate); if (newIGPosts.Length > 0 && newIGPosts[newIGPosts.Length - 1].success) { //Set the most recent posts date: dbfeed.LastPostDate = newIGPosts[newIGPosts.Length - 1].postDate; } foreach (InstagramProcessorResponse response in newIGPosts) { List <RespondChannel> invalidChannels = new List <RespondChannel>(); foreach (RespondChannel subbedGuild in dbfeed.SubscribedChannels) { if (response.success) { //Create component builder: IGComponentBuilder component = new IGComponentBuilder(response); //Create embed response: IGEmbedBuilder embed = new IGEmbedBuilder(response); if (!response.success) { //Failed to process post: Console.WriteLine("Failed to process post."); return; } else if (response.isVideo) { if (response.stream != null) { //Response with stream: using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.mp4", "An Instagram Video."); // get channel: IMessageChannel chan = null; try { chan = _client.GetChannel(ulong.Parse(subbedGuild.ChannelID)) as IMessageChannel; } catch { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } if (chan != null) { //send message await chan.SendFileAsync(attachment, embed : embed.AutoSelector(), components : component.AutoSelector()); } else { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } } } else { //Response without stream: // get channel: IMessageChannel chan = null; try { chan = _client.GetChannel(ulong.Parse(subbedGuild.ChannelID)) as IMessageChannel; } catch { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } if (chan != null) { //send message await chan.SendMessageAsync(response.contentURL.ToString(), embed : embed.AutoSelector(), components : component.AutoSelector()); } else { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } } } else { if (response.stream != null) { using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.jpg", "An Instagram Image."); // get channel: IMessageChannel chan = null; try { chan = _client.GetChannel(ulong.Parse(subbedGuild.ChannelID)) as IMessageChannel; } catch { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } if (chan != null) { //send message await chan.SendFileAsync(attachment, embed : embed.AutoSelector(), components : component.AutoSelector()); } else { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } } } else { // get channel: IMessageChannel chan = null; try { chan = _client.GetChannel(ulong.Parse(subbedGuild.ChannelID)) as IMessageChannel; } catch { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } if (chan != null) { //send message try { await chan.SendMessageAsync(embed : embed.AutoSelector(), components : component.AutoSelector()); }catch (Exception e) { Console.WriteLine("Error sending subscription message. Error: " + e); invalidChannels.Add(subbedGuild); } } else { Console.WriteLine("Cannot find channel. Removing from DB."); invalidChannels.Add(subbedGuild); } } } } else if (response.error == "NullAccount") { Console.WriteLine("Removing null account: " + dbfeed.InstagramID); invalidChannels.Add(subbedGuild); } else { //TODO: Decide if the user should be informed or not. May create spam. Console.WriteLine("Failed auto post. ID: " + dbfeed.InstagramID); var chan = _client.GetChannel(ulong.Parse(subbedGuild.ChannelID)) as IMessageChannel; string igUsername = await instagram.GetIGUsername(dbfeed.InstagramID); await chan.SendMessageAsync("Failed to get latest posts for " + igUsername + ". Use `/unsubscribe " + igUsername + "` to remove the inaccessible account."); } } //Remove all invalid channels: invalidChannels.ForEach(item => dbfeed.SubscribedChannels.RemoveAll(c => c.ChannelID.Equals(item.ChannelID))); } //Update database: await this.FollowedAccountsContainer.ReplaceOneAsync(x => x.InstagramID == dbfeed.InstagramID, dbfeed, new ReplaceOptions { IsUpsert = true }); // Wait to prevent spamming IG api: // 10 seconds await Task.Delay(10000); } } catch (Exception e) { Console.WriteLine("Failed to get updates for IG account. Error: " + e); } } } catch (Exception e) { Console.WriteLine("Error with update loop: " + e); } finally { //Always mark as done loop when exiting: InSubLoop = false; Console.WriteLine("Done."); } }
/// <summary> /// Centralized method to handle all Instagram links and respond to text based messages (No slash commands). /// </summary> /// <param name="url">The Instagram URL of the content</param> /// <param name="context">The discord context of the message</param> /// <returns></returns> private static async Task Responder(string url, ICommandContext context) { // Check whitelist: if (!Whitelist.IsServerOnList(context.Guild.Id)) { // Ignore if not on list: return; } using (context.Channel.EnterTypingState()) { // Get IG account: InstagramProcessor instagram = new InstagramProcessor(InstagramProcessor.AccountFinder.GetIGAccount()); //Process Post: InstagramProcessorResponse response = await instagram.PostRouter(url, (int)context.Guild.PremiumTier, 1); //Check for failed post: if (!response.success) { await context.Message.ReplyAsync(response.error); return; } // Embed builder: IGEmbedBuilder embed = new IGEmbedBuilder(response, context.User.Username); IGComponentBuilder component = new IGComponentBuilder(response, context.User.Id); if (response.isVideo) { if (response.stream != null) { //Response with stream: using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.mp4", "An Instagram Video."); await context.Message.Channel.SendFileAsync(attachment, embed : embed.AutoSelector(), components : component.AutoSelector()); } } else { //Response without stream: await context.Message.ReplyAsync(response.contentURL.ToString(), embed : embed.AutoSelector(), allowedMentions : AllowedMentions.None, components : component.AutoSelector()); } } else { if (response.stream != null) { using (Stream stream = new MemoryStream(response.stream)) { FileAttachment attachment = new FileAttachment(stream, "IGMedia.jpg", "An Instagram Image."); await context.Channel.SendFileAsync(attachment, embed : embed.AutoSelector(), components : component.AutoSelector()); } } else { await context.Message.ReplyAsync(embed : embed.AutoSelector(), allowedMentions : AllowedMentions.None, components : component.AutoSelector()); } } //Try to remove the embeds on the command post: DiscordTools.SuppressEmbeds(context); } }