• This repository has been archived on 21/Jan/2021
  • Stars
    star
    523
  • Rank 84,684 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 10 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple, extensible and powerful one stop personal assistant

Assistant

A super simple, extensible and powerful personal assistant, just like your shell, with the power of HTML.

short-intro

What is that?

Assistant is more like a hubot with rich HTML interface(Om component), or like a Siri on your desktop. It consists of multiple dispatchers(processors) and cards. Dispatcher(processor) process the text commands, then put the result into the result channel. Assistant will use the correspond card(a Om component) to show the data.

How to use?

Make sure you have Leiningen installed, if not, you can use brew install leiningen to install.

WARN:

  1. Someone has issues with the older version of leiningen, so please upgrade it to 2.5.3(or at least >=2.4.3) first if you are using an older version of leiningen.
  2. Many of services needs api key to work, since they are making requests to those services. Now most of the services will complain about no aip keys found in ~/.assistant, luckly it will also tell you where to get one, for free :-)
git clone [email protected]:29decibel/assistant.git && cd assistant
lein cljsbuild once && lein node-webkit-build

After that, you will find a stand alone app in the release folder. Right now it only build the app for Mac. Will support Linux and Windows later on. Make sure you have proper configuration in your ~/.assistant for specific commands, you can find a example config file here.

Here is a simple diagram of how it works

assistant-structure

Build-in cards

image-list-card

image-list-card-hand-draw

  • Data Structure:
{ :card :image-list-card
  :content [
    {:url "http://example-url" :image "http://some-image-url/a.jpg" :title "Item title"}
    ...
  ]
}

list-card

list-card-hand-draw

  • Data Structure:
{ :card :list-card
  :content [
    {:url "http://example-url" :title "Item title"}
    ...
  ]
}

markdown-card

  • Data Structure:
{ :card :markdown-card
  :content "## Markdown title \n Content area... \n ![image](http://someawesome-image.jpg)"
}

info-card

Display error, warn, info or success information card to the user.

  • Data Structure:
{ :card :info-card
  :content "Your config not correct, please add :jenkins :username in your ~/.assistant"}
  :info-type "error" }

Write your plugin

  1. Write a processor

A processor is just a function take a result channel and the text user typed in, then do what ever you want, at last put the result into the chanel.

In this case, we make a request to Jira api, then put the JSON response into the channel and tell assistant to use jira card to render the result.

(defn jira-dispatcher [result-chan text]
  (go (let [response (<! (http/get (str endpoint "/rest/api/2/issue/" text) {:basic-auth {:username username :password password}}))
            m (:body response)
            error (:errorMessages m)
            issue-key (:key m)]
        (when issue-key
          (>! result-chan {:type :jira :content m :input text})))))
  1. Write a card

You don't have to write a card to show the result of your stuff, we have some built in cards. But if those cards not what you want, then you can always easily wrap your own. Here is a simple card(Om component) of for Jira issue.

(defn jira-view [data owner]
  (reify
    om/IRender
    (render [_]
            (dom/div #js {:className "clearfix"}
                     (common/link (str endpoint "/browse/" (:input data)) (dom/h4 nil (-> data :content :key) "  " (-> data :content :fields :summary)))
                     (dom/p #js {:dangerouslySetInnerHTML #js {:__html (clojure.string/replace (or
  1. Register
  • Register processor

    (register-dispatcher :jira jira-dispatcher "jira [issue-number] -- find jira issue")
  • Register card

    (register-card :jira jira-view)
  • Register CSS(optional) If you want to provide customized CSS to your component, you can do that through register-css:

    (register-css [:.jenkins-card
                   [:code {:max-height "30px" :height "30px" :overflow "auto"}]
                   [:a {:display "inline-block" :min-width "200px"}]])
  • Register plugin namespace Add your plugin namespace name to ~/.assistant-plugins file:

    # here is a list of your awesome plugins you want to enabled
    # WARN: If your plugin used dash, then you need to convert it to underscore, since it's javascript
    #       assistant.plugins.your-awesome-plugin --> assistant.plugins.your_awesome_plugin
    assistant.plugins.your_awesome_plugin
    

Here is a source code of example plugin for looking up Clojure doc.

  1. Build
lein cljsbuild clean
lein cljsbuild once
  1. Build standalone app
lein node-webkit-build

Core APIs

  1. assistant.core/register-dispatcher > Register your dispatcher/processor.
```clojure
(register-dispatcher :dribble dribbble-dispatcher "dribble -- show popular designs from dribbble")
```
  1. assistant.core/register-card > Register your custom card.
```clojure
(register-card :jira jira-card)
```
  1. assistant.core/register-css > Using noprompt/garden to register your custom css for your card.
```clojure
(register-css [:.map
               [:iframe {:width "100%" :height "400px" :border "none"}]
               [:img {:margin-top "2px auto"}]])
```
  1. assistant.core/valid-config > Check if given config exists. If not then show a error card.
```clojure
;; Here is a example how to check config informations
(defn check-jenkins-config []
  (and (valid-config [:jenkins :host] "Please make sure following config exists in your ~/.assistant: :jenkins {:host}")
       (valid-config [:jenkins :token] "Please make sure following config exists in your ~/.assistant: :jenkins {:token }")
       (valid-config [:jenkins :username] "Please make sure following config exists in your ~/.assistant: :jenkins {:username}")
       (valid-config [:jenkins :password] "Please make sure following config exists in your ~/.assistant: :jenkins {:password}")))
```

TODO

  • Add a general card for errors(configuration checking)
  • Add clear command to clear all cards
  • markdown-card
  • Pipes (dispatcher can pass result/clojure data structure to next dispatcher)
  • Storage service support
  • Check required parameters
  • System services
  • Generic cards(List Card, Image Card, Readable Article List Card, JSON Viewer Card)
  • Auto save app state
  • Command line like style
  • Create dot file if not exists

More cards

FAQ

  1. Why this exists? I am not trying to build a new shell, or revolutionize shell interface. I am also not trying to build a Alfred alternative. Since, I think, it's all start from different places to solve different problems. Shell is great, lightweight and highly composable(due to the abstraction of texts) through pipes. Alfred is more like a luncher, though nowadays it includes quite flexible work-flows, but it's interface still constrained by lists.

The idea behind Assistant is try to use minimal concepts, elements(processor + card) to solve problems, but also at the same time make it highly extensible. I am trying to build a simple mind model text --> process --> result(JSON/map/array) -> card. Before ReactJS exists, card parts is always become a mess. Either it will be very hard to control the modularity or it has too much hassle or mentally feel complicated. But since ReactJS's component is just like a card. Itself accepts data, then return virtual DOM elements, that's it, no more, no less. Finally I feel relieved. :-)

Om push it into a higher level, so you can write even less code, avoid struggling another new JSX format. Have to say writing UI in Om is the first time I feel fun.

  1. Why there are two places for plugins? Where should I put my plugins? The initial idea is to have a bunch of built in services, they are all lived in src/assistant/services. It's also part of the git repo. But if you have any personal plugins want to use, you can create cljs file in plugins folder. Leinbuild will also pick it up.

Later on I plan to use some similar plugin installation system like Lighttable. But it needs some time.

  1. Why it shows a blank card? Sorry for that if you ever saw it, that's probably because you don't have certain API keys for some services. So the result is empty, also if the card doesn't check the result properly it might render a empty card. I've added a new function valid-config and a built in info-card. So before the processor runs, it will check if the config exists, if not, it will put a error result into the channel, then the info-card will render and show the message.

I will try to make this config check process much simpler later on. Also I am very open to ideas on how to improve this tool to make it more useful.

Inspired by

Credits goes to

Donation

Buy me a Kindle book πŸ“–

Build with β™₯ Clojure+Clojurescript.

More Repositories

1

html2markdown

simple and flexible html to markdown converter
Ruby
71
star
2

readit

a simple api client for readability
Ruby
49
star
3

codeschool-vim-theme

codeschool vim theme
Vim Script
31
star
4

vim-stringify

Turn your raw template into concated string
Vim Script
29
star
5

kindler

Kindle mobi format ebook generator
Ruby
22
star
6

hackernews-feed

HackerNews full readable article Rss feeds
JavaScript
20
star
7

talk-to-my-books

A standalone desktop app for talking to my books (PDF,epub)
TypeScript
9
star
8

void_inbox

A simple email inbox web app to read your not so important emails
Elixir
9
star
9

versionone-cli

command line interactive with VersionOne
CoffeeScript
8
star
10

go-combo

YUI3 combo handler using Go
Go
8
star
11

digestor

Personal digest mail service
Go
6
star
12

omniauth-readability

an omniauth strategy for readability
Ruby
5
star
13

dotfiles

Personal config files for vim, tmux, iterm2
Vim Script
4
star
14

bean-note

simple and elegant note app
JavaScript
3
star
15

doupod

a script to grab all my douban fm's loved song to iTunes
Ruby
3
star
16

reading-octopress-plugin

a plugin display readings of article and books on octopress
Ruby
3
star
17

instait

Ruby
2
star
18

mastodon-md

A little utility to download mastodon posts into markdown files (Hugo compatible)
TypeScript
2
star
19

readability-cli

A readability cli/bun script to extract article from given URL, without NodeJS
TypeScript
2
star
20

simple_run

Elixir
1
star
21

fitparser-bridge

Node JS wrapper of rust fitparse package
Rust
1
star
22

live_comments

Elixir
1
star
23

feedex

Elixir
1
star
24

dominant_colors

Get dominant colors (k-means) from given image (wrapper on top of kmeans_colors)
Elixir
1
star
25

thread_prettier

make forum threads looks prettier
Ruby
1
star
26

buz_phone

buzz phone app Phonegap+Spinejs
JavaScript
1
star
27

es_exif

Elixir
1
star
28

yew-app

Rust
1
star
29

tiny-notes

Nunjucks
1
star
30

simple-md

JavaScript
1
star
31

my-letter

Rust
1
star
32

fit_parser

Elixir Garmin fit files parser
Elixir
1
star
33

amy_admin

a simple but clever rails admin
Ruby
1
star
34

listen_down

songs download script, self pleasure use only
Ruby
1
star
35

feed_bucket

Elixir
1
star
36

stringer-lte

Another RSS reader
JavaScript
1
star
37

dot-hammerspoon

Lua
1
star
38

letter_reads

A central place to subscribe and read your newsletters
1
star
39

webriem

online expense system
JavaScript
1
star
40

rum-quickstart

Clojure
1
star