{"id":23114343,"url":"https://github.com/syxanash/joshua_bot","last_synced_at":"2025-08-16T20:31:59.129Z","repository":{"id":46725632,"uuid":"44495062","full_name":"syxanash/joshua_bot","owner":"syxanash","description":"A plugins based Telegram Bot written in Ruby","archived":false,"fork":false,"pushed_at":"2024-06-10T16:45:56.000Z","size":2388,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-06-10T18:52:15.732Z","etag":null,"topics":["chatgpt","ruby","security-camera","telegram","telegram-bot","telegram-chatgpt"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/syxanash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-18T20:25:11.000Z","updated_at":"2024-06-10T16:45:59.000Z","dependencies_parsed_at":"2022-08-25T14:41:51.215Z","dependency_job_id":"7a8ca0b7-5449-4926-aaf5-f05a983e727d","html_url":"https://github.com/syxanash/joshua_bot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syxanash%2Fjoshua_bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syxanash%2Fjoshua_bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syxanash%2Fjoshua_bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syxanash%2Fjoshua_bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/syxanash","download_url":"https://codeload.github.com/syxanash/joshua_bot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230057963,"owners_count":18166173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatgpt","ruby","security-camera","telegram","telegram-bot","telegram-chatgpt"],"created_at":"2024-12-17T03:29:32.599Z","updated_at":"2024-12-17T03:29:34.797Z","avatar_url":"https://github.com/syxanash.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Joshua\n\n![logo](other/doc_assets/joshua.gif)\n\nA *plugins* based bot for [Telegram](https://telegram.org/) messaging app written in Ruby.\n\n## Installation\n\nInstall required dependencies:\n\n```\n$ sudo apt-get install ffmpeg wget\n```\n\nClone this repository and then run `bundle` to install the dependencies.\n\n```\n$ git clone git@github.com:syxanash/joshua_bot.git\n$ cd joshua_bot\n$ bundle install\n```\n\n## Usage\n\nEnter a valid bot API token in `config.json` (see **Configure** below) then run the bot with:\n\n```\n$ ruby bot.rb\n```\n\nA log file will be created in `/tmp/joshua_bot_tmp` directory with a random name (e.g. `bot_1b3510f004bd.log`)\n\n## Configure\n\n### Bot API Token\n\nBefore running the bot you need to add a telegram API key for your bot to the file `config.json`. Check out the official [telgram documentation](https://core.telegram.org/bots#3-how-do-i-create-a-bot) to achieve this.\n\nHere's an example of a `config.json` once you have your API key set up:\n\n```json\n{\n  \"token\": \"103414657:AAGh0I6l-CKf_TDu6CUNa7c7MgnfRbUDzMQ\",\n  \"prod\": true,\n  \"temp_directory\": \"/tmp/joshua_bot_tmp\",\n  \"plugin_folder\": \"basic\",\n  \"password\": \"\",\n  \"startup_commands\": [\"/xkcd\"],\n  \"openai\": {\n    \"token\": \"\",\n    \"recognize_plugins\": true,\n    \"max_interaction_history\": 5,\n    \"log_prompts\": false\n  }\n}\n```\n\n### Plugins\n\nIf you take a look at the folder `lib/plugins/` you will find different sub folders containing various plugins inside. By default the plugins loaded on the bot are in `basic/`. Alternatively you can specify a different folder in the `config.json` modifying the value `plugin_folder` (e.g. `\"spioncino\"`) .\n\nYou can create your own folder of plugins and drag plugins from other folders by making a new folder in `lib/plugins/`, for instance:\n\n```\n$ mkdir lib/plugins/workinprogress\n```\nOnce you've done that you can specify the folder `\"workinprogress\"` inside `config.json`.\n\n**Notice** that the plugin `help.rb` will always be loaded since it resides in the root directory of the plugins `lib/plugins`. You can place in this folder all the plugins which will always be loaded by the bot.\n\n### Bot Password\n\nIf you want to be the only one talking to your bot you can add a **tiny** layer of security setting up a *bot password*. By doing so everytime you start the conversation with the bot it will ask you for a password before interpreting various commands.\n\nYou can set a bot password in the `config.json` under the value `\"password\"`.\n\n## Create Plugins\n\nEach plugin is a class which extends the class `AbsPlugin`. A plugin should have the following four methods:\n\n* `initialize` (not mandatory)\n* `command`\n* `show_usage`\n* `do_stuff`\n* `examples` (see [OpenAI Integration](https://github.com/syxanash/joshua_bot#openai-integration))\n\nYou can place a new plugin in the folder `lib/plugins` or inside a subfolder of this directory to group plugins all your plugins. For example `basic/` and `spioncino/` are two different plugin folders.\n\n### initialize\n\nIt's a method used to *initialize* class variables and other settings used by the plugin. This method will be called when the bot is loading the plugins for the first time. Also see Ruby [object initialization](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/objinitialization.html).\n\n### command\n\nThis method should return the **regular expression** used to match a command which the bot will interpret. For instance:\n\n```rb\ndef command\n  /^\\/fortune$/\nend\n```\n\nIn this case the plugin will be activated upon entering the command `/fortune`. A slightly more complex command could be instad:\n\n```rb\ndef command\n  /(^\\/takephoto$|photo)/\nend\n```\n\nWhich will interpret either `/takephoto` or simply `photo`.\n\n### show_usage\n\nYou can display a help message to show the user the correct usage of the plugin. This method will be called when the user invokes the command in a wrong way for example if the command requires additional parameters.\n\nFor instance the plugin [Spione](lib/plugins/spioncino/spione.rb) will call the method `show_usage` if the user invokes the command `/spione` without parameters. A correct usage of the plugin Spione would be `/spione on`.\n\n### do_stuff\n\nThis method will contain the actual code executed when the command is invoked. You can send simple text messages to the user (see the plugin [Fortune](lib/plugins/basic/fortune.rb)), images (see [Xkcd](lib/plugins/basic/xkcd.rb) plugin) or audio messages (see [Say](lib/plugins/spioncino/say.rb)).\n\n## Interacting with plugins\n\nYou can interact with plugins either by passing **additional parameters** when calling the plugin or by asking the user further questions by **reading the buffer**. An analogy to this could be passing information to a command line tool either by passing _arguments_ or using `STDIN` 😄\n\n### Additional Parameters\n\nAdditional command's parameters will be stored in the formal parameter `match_result` of the method `do_stuff`. The plugin's additional parameters will be created if you define a regular expression which accepts extra parameters like:\n\n`/^\\/diceroll\\s?(\\d*?)?$/`\n\nIn this case **DiceRoll** plugin can be invoked by using the command `/diceroll` or you can pass an extra parameter as an integer like so: `/diceroll 50` (this plugin will now generate a random number from 1-50). `match_result` is an array which will contain all the captured variables of the matched plugin's regex.\n\n\u003cimg src=\"other/doc_assets/screenshot_additional_parameters.png\" alt=\"screenshot_additional_parameters\" width=\"400\" height=\"490\" /\u003e\n\n### Read Buffer\n\nIf you want your plugins to be more interactive asking questions and evaluating replies, more like a conversation with the user, you can use `read_buffer()`. This method must be invoked in the `do_stuff` block of your plugin.\n\nHere's an example of a simple plugin which makes the addition of two numbers:\n\n```rb\ndef do_stuff(match_results)\n  bot.api.send_message(chat_id: message.chat.id, text: \"what's the first number?\")\n  first_number = read_buffer\n\n  bot.api.send_message(chat_id: message.chat.id, text: \"what's the second number?\")\n  second_number = read_buffer\n    \n  bot.api.send_message(chat_id: message.chat.id, text: \"I'm not a calculator so F𝔘Ⓒk off\")\n  sleep(3)\n  bot.api.send_message(chat_id: message.chat.id, text: \"it's #{first_number.to_i + second_number.to_i}...\")\nend\n```\n\nAnd this is going to be the result:\n\n\u003cimg src=\"other/doc_assets/screenshot_session_buffer.png\" alt=\"screenshot_session_buffer\" width=\"400\" height=\"490\" /\u003e\n\nSome plugins which use the session buffer are:\n\n* [basic/lyrics.rb](lib/plugins/basic/lyrics.rb)\n* [basic/randomlogo.rb](lib/plugins/basic/randomlogo.rb)\n* [basic/morra.rb](lib/plugins/basic/morra.rb)\n* [spioncino/remote.rb](lib/plugins/spioncino/remote.rb)\n\n### Startup commands\n\nWhen a bot is protected by **password** you can execute a sequence of commands as soon as the user logs in. Take a look at `config.json` you'll find an array called `startup_commands`. You can edit this variable and add your list of startup commands that you wish to execute after logging in.\n\nFor example:\n\n```json\n  \"startup_commands\": [\"/diceroll 12\", \"/ping\", \"/morra\"]\n```\n\nAnd this will be the output after entering the password correctly:\n\n\u003cimg src=\"other/doc_assets/screenshot_startup_commands.png\" alt=\"screenshot_startup_commands\" /\u003e\n\n### Stopping a plugin\n\nIn order to stop a bot from asking further inputs and replies from a user, perhaps because of a bug or an unforeseen loop condition in your code, you can type the command `/cancel` and the plugin will terminate its execution.\n\n### Logging\n\nBy default, a log file will be created in `/tmp/joshua_bot_tmp` (you can change this by editing the `temp_directory` name in `config.json`). Alternatively, if you'd like to redirect all output to STDOUT while testing your bot, simply change the variable `prod` to `false` in `config.json`.\n\n## OpenAI Integration\n\nThanks to the [OpenAI APIs](https://platform.openai.com/docs), you can chat with Joshua Bot using ChatGPT. This feature is **completely optional** and this bot will work even without OpenAI. OpenAI APIs are used to interpret commands of various plugins or to just talk to your bot using ChatGPT.\nTo enable the bot to use OpenAI, enter your [OpenAI API Token](https://platform.openai.com/account/api-keys) in `config.json`.\n\n### Interpreting commands\nThis feature is toggled on by default, so whenever you send a message to the bot without directly invoking a command, it will automatically try to interpret it as a command for executing a plugin. \n\n\u003cimg src=\"other/doc_assets/screenshot_plugins_conversation.png\" alt=\"screenshot chatgpt\" height=\"400\"\u003e\n\n*(In this picture the [XKCD comic](lib/plugins/basic/xkcd.rb), the [dice roll](lib/plugins/basic/diceroll.rb) number and [battery status](lib/plugins/basic/battery.rb) are plugins executed by the bot)*\n\nIn order to let the bot recognize and execute plugins simply by chatting with it, you will need to add the examples when creating new custom plugins. _Examples_ will be used to train the bot to recognize the text based on the description and execute the related command.\n\nThis is the format you will need to follow:\n\n```rb\ndef examples\n  [\n    { command: '/diceroll',    description: 'return a random number from 1 to 6' },\n    { command: '/diceroll 10', description: 'return a random number from 1 to 10' }\n  ]\nend\n```\n\nMake sure the command in _examples_ matches the regex in `command` method of your plugin!\nTake a look at the demo plugins to have an idea of how to write your own plugin and to make the bot execute commands: [morra.rb](lib/plugins/basic/morra.rb), [lyrics.rb](lib/plugins/basic/lyrics.rb), [randomlogo.rb](lib/plugins/basic/randomlogo.rb)\u003cbr\u003e\nIf you'd like to talk to the bot only using ChatGPT without any command translation, you can toggle this feature off by setting the flag `recognize_plugins` to `false` in `config.json`.\n\n### Bot Personality\n\nThe default personality of Joshua is the following:\n\n```\nJoshua is a helpful chatbot who enjoys chatting with any human who interacts with him.\n```\n\nThis was hardcoded inside [ai_handler.rb](lib/ai_handler.rb). You can add extra traits to your bot in a personality file, which by default is called `personality.txt`. You can also rename or specify your own file in `config.json`.\n\nHere's another example of more personality you can add to your bot inside `personality.txt`:\n\n```\nHe's a very sarcastic bot that lives inside a Raspberry Pi (Zero W to be precise).\nHe really likes the movie WarGames and always tries his best to put some quotes from this movie.\n```\n\n### Voice Messages\n\nWhen OpenAI integration is enabled and the user sends a voice message to the bot, this will automatically be transcribed using [Whisper APIs](https://openai.com/blog/introducing-chatgpt-and-whisper-apis). The transcription will then be used for interpreting plugins or communicating with ChatGPT.\n\n\u003cimg src=\"other/doc_assets/screenshot_voice_messages.png\" alt=\"screenshot sending voice messages\" height=\"250\"\u003e\n\n## Spioncino\n\n![ruby lady](other/doc_assets/ruby-lady.png)\n\nYou should definitely tell your partner about an awesome implementation of this bot as a simple surveillance system for your mansion: [spioncino](SPIONCINO.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyxanash%2Fjoshua_bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyxanash%2Fjoshua_bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyxanash%2Fjoshua_bot/lists"}