Skip to content

Commit

Permalink
Inital Work (0.1)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattiascibien committed Jul 20, 2019
1 parent 28601ea commit 5734e19
Show file tree
Hide file tree
Showing 15 changed files with 963 additions and 0 deletions.
599 changes: 599 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions .idea/.idea.image-search-bot/.idea/indexLayout.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/.idea.image-search-bot/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/.idea.image-search-bot/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Config/BotConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace ImageSearchBot.Config
{
public class BotConfig
{
public string Prefix { get; set; }

public List<string> GreetingsMessages { get; set; }

public List<string> Responses { get; set; }
}
}
12 changes: 12 additions & 0 deletions Config/ImageSearchConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace ImageSearchBot.Config
{
public class ImageSearchConfig
{
public string Type { get; set; }

public string Query { get; set; }

public bool? IncludeNsfw { get; set; }

}
}
9 changes: 9 additions & 0 deletions Config/RootConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ImageSearchBot.Config
{
public class RootConfig
{
public BotConfig BotConfig { get; set; }

public ImageSearchConfig ImageSearchConfig { get; set; }
}
}
40 changes: 40 additions & 0 deletions ImageSearch/BingImageSearch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Net;
using ImageSearchBot.Config;
using Microsoft.Azure.CognitiveServices.Search.ImageSearch;

namespace ImageSearchBot.ImageSearch
{
public class BingImageSearch : ImageSearch
{
private readonly ImageSearchClient _client;

public BingImageSearch(string botPrefix, ImageSearchConfig config) : base(botPrefix, config)
{
var keyEnvVar = $"{BotPrefix}_BING_KEY";
var subscriptionKey = Environment.GetEnvironmentVariable(keyEnvVar);
_client = new ImageSearchClient(new ApiKeyServiceClientCredentials(subscriptionKey));
}

public override void Dispose()
{
_client.Dispose();
}

public override byte[] GetImage(int index, int count)
{
var imageResults = _client.Images.SearchAsync(
Config.Query,
safeSearch: Config.IncludeNsfw ?? false ? "Off" : "Moderate",
count: count).Result; //search query

var clampedIndex = Math.Clamp(index, 0, imageResults.Value.Count-1);

var imageUrl = imageResults.Value[clampedIndex].ContentUrl;
using (var webClient = new WebClient())
{
return webClient.DownloadData(imageUrl);
}
}
}
}
29 changes: 29 additions & 0 deletions ImageSearch/IImageSearch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using ImageSearchBot.Config;

namespace ImageSearchBot.ImageSearch
{
public interface IImageSearch : IDisposable
{
string BotPrefix { get; }

byte[] GetImage(int index, int count);
}

public abstract class ImageSearch : IImageSearch
{
public string BotPrefix { get; }

protected ImageSearchConfig Config { get; }

protected ImageSearch(string botPrefix, ImageSearchConfig config)
{
BotPrefix = botPrefix;
Config = config;
}

public abstract void Dispose();

public abstract byte[] GetImage(int index, int count);
}
}
101 changes: 101 additions & 0 deletions ImgBot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.IO;
using ImageSearchBot.Config;
using ImageSearchBot.ImageSearch;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;

namespace ImageSearchBot
{
public class ImgBot
{
private const int MaxImages = 500;

private readonly TelegramBotClient _bot;
private readonly User _me;
private readonly BotConfig _config;
private readonly IImageSearch _imageSearch;
private readonly Random _random;

public ImgBot(BotConfig config, IImageSearch imageSearch)
{
_random = new Random();

_config = config;
_imageSearch = imageSearch;
_bot = new TelegramBotClient(Environment.GetEnvironmentVariable($"{_config.Prefix}_TELEGRAM_KEY"));

_me = _bot.GetMeAsync().Result;

_bot.OnMessage += BotOnMessageReceived;
_bot.OnMessageEdited += BotOnMessageReceived;
_bot.OnCallbackQuery += BotOnCallbackQueryReceived;
_bot.OnInlineQuery += BotOnInlineQueryReceived;
_bot.OnInlineResultChosen += BotOnChosenInlineResultReceived;
_bot.OnReceiveError += BotOnReceiveError;
}

private void BotOnReceiveError(object sender, ReceiveErrorEventArgs e)
{

}

private void BotOnChosenInlineResultReceived(object sender, ChosenInlineResultEventArgs e)
{

}

private void BotOnInlineQueryReceived(object sender, InlineQueryEventArgs e)
{

}

private void BotOnCallbackQueryReceived(object sender, CallbackQueryEventArgs e)
{

}

private async void BotOnMessageReceived(object sender, MessageEventArgs e)
{
var message = e.Message;

var isPrivate = e.Message.Chat.Type == ChatType.Private;

if (isPrivate || message.Text.Contains($"@{_me.Username}"))
{
// TODO: configurable keywords
if (message.Text.ToLower().Contains("photo"))
{
var image = _imageSearch.GetImage(_random.Next(MaxImages), MaxImages);

using (var memoryStream = new MemoryStream(image))
{
await _bot.SendPhotoAsync(
message.Chat.Id,
memoryStream,
_config.Responses[_random.Next(_config.Responses.Count)]);
}
}
else
{
await _bot.SendTextMessageAsync(message.Chat.Id,
_config.GreetingsMessages[_random.Next(_config.GreetingsMessages.Count)]);
}
}
}

public void Run()
{
_bot.StartReceiving(Array.Empty<UpdateType>());
Console.WriteLine($"@{_me.Username}: started");
}

public void Stop()
{
Console.WriteLine($"@{_me.Username}: stopped");
_bot.StopReceiving();
}
}
}
66 changes: 66 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using dotenv.net;
using ImageSearchBot.Config;
using ImageSearchBot.ImageSearch;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace ImageSearchBot
{
public static class Program
{
private static readonly List<ImgBot> Bots = new List<ImgBot>();

private static readonly ManualResetEvent ExitEvent = new ManualResetEvent(false);

public static void Main(string[] args)
{
DotEnv.Config(false);

Console.CancelKeyPress += ConsoleOnCancelKeyPress;

var dir = args.Length <= 0 ? Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) : args[0];

// retrieve bots config inside the directory
var configs = Directory.GetFiles(dir)
.Where(file => Path.GetFileName(file).ToLower().EndsWith(".botconfig.json")).ToList();
if (configs.Count == 0)
{
Console.Error.WriteLine("No bots configured. Add one like this mybot.botconfig.json");
Environment.Exit(1);
return;
}

foreach (var config in configs)
{
var contents = File.ReadAllText(config);
var cfg = JsonConvert.DeserializeObject<RootConfig>(contents,
new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
var imageSearchType = Type.GetType(cfg.ImageSearchConfig.Type);
var imageSearch = (IImageSearch)Activator.CreateInstance(imageSearchType, cfg.BotConfig.Prefix, cfg.ImageSearchConfig);
var imgBot = new ImgBot(cfg.BotConfig, imageSearch);
Bots.Add(imgBot);
Task.Run(() => imgBot.Run());
}

ExitEvent.WaitOne();
Console.CancelKeyPress -= ConsoleOnCancelKeyPress;
Bots.ForEach(b => b.Stop());
}

private static void ConsoleOnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
ExitEvent.Set();
}
}
}
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# image-search-bot
Configurable apps for running Telegram Bots that responds to photo Image Queries

## Bots using this framework

* Mike's Mother - Bot That Looks for images of Cara Buono, Mike's mother in Stranger Things.

## Deveopment

* Register your bot(s) using @botfather.
* ...
25 changes: 25 additions & 0 deletions image-search-bot.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RootNamespace>ImageSearchBot</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="dotenv.net" Version="1.0.6" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.Search.ImageSearch" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Telegram.Bot" Version="14.12.0" />
</ItemGroup>

<ItemGroup>
<None Update=".env">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="mikesmother.botconfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions image-search-bot.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "image-search-bot", "image-search-bot.csproj", "{46E52E03-6EDD-45F2-838A-B9E994A13D8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46E52E03-6EDD-45F2-838A-B9E994A13D8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46E52E03-6EDD-45F2-838A-B9E994A13D8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46E52E03-6EDD-45F2-838A-B9E994A13D8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46E52E03-6EDD-45F2-838A-B9E994A13D8B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
24 changes: 24 additions & 0 deletions mikesmother.botconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"botConfig": {
"prefix": "MMBOT",
"greetingsMessages" : [
"Hello. I am Mike's Mother bot!",
"Nice to meet you.",
"Ask me something.",
"Whats about a photo of Mike's Mother?"
],
"responses": [
"Here she is, gorgeous as always!",
"Here you are.",
"Here it is"
],
"keywords": [
"photo"
]
},
"imageSearchConfig": {
"type": "ImageSearchBot.ImageSearch.BingImageSearch",
"query": "cara buono",
"includeNsfw": false
}
}

0 comments on commit 5734e19

Please sign in to comment.