Skip to content

Commit c325bcd

Browse files
committed
initial commit
0 parents  commit c325bcd

30 files changed

+682
-0
lines changed

.github/ISSUE_TEMPLATE.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!--- Provide a general summary of the issue in the Title above -->
2+
<!--- If you want to deploy a recipe to the global repository, please prefix your issue title with [Deploy] -->
3+
4+
### Service
5+
<!--- What service is this recipe for? -->
6+
7+
### Link to your repository
8+
<!--- Please paste the link to your recipe repository -->
9+
10+
### Additional Information
11+
<!--- Not obligatory -->

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Stefan Malzner
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Franz 5 - Plugins
2+
[Franz 5](https://github.com/meetfranz/franz) plugins are now called __recipes__.
3+
4+
## How to install a recipe
5+
In Franz 5, recipes are now served via a central repository. Except for development purposes you don't need to manually install a recipe any longer.
6+
7+
__To add a new service:__
8+
* Go to your Franz 5 App
9+
* Search & add the required service
10+
* Et voila, simple as that!
11+
12+
## How to develop, test and deploy recipes
13+
[Read the documentation](/docs)
14+
15+
## Example Recipes
16+
* [Discord](https://github.com/meetfranz/recipe-discord)
17+
* [Flowdock](https://github.com/meetfranz/recipe-flowdock)
18+
* [Gmail](https://github.com/meetfranz/recipe-gmail)
19+
* [Grape](https://github.com/meetfranz/recipe-grape)
20+
* [GroupMe](https://github.com/meetfranz/recipe-groupme)
21+
* [Hangouts](https://github.com/meetfranz/recipe-hangouts)
22+
* [HipChat](https://github.com/meetfranz/recipe-hipchat)
23+
* [Inbox by Gmail](https://github.com/meetfranz/recipe-inbox)
24+
* [Mattermost](https://github.com/meetfranz/recipe-mattermost)
25+
* [Messenger](https://github.com/meetfranz/recipe-messenger)
26+
* [MySMS](https://github.com/meetfranz/recipe-mysms)
27+
* [Rocket.Chat](https://github.com/meetfranz/recipe-rocketchat)
28+
* [Skype](https://github.com/meetfranz/recipe-skype)
29+
* [Slack](https://github.com/meetfranz/recipe-slack)
30+
* [Telegram](https://github.com/meetfranz/recipe-telegram)
31+
* [Tweetdeck](https://github.com/meetfranz/recipe-tweetdeck)
32+
* [WhatsApp](https://github.com/meetfranz/recipe-whatsapp)
33+
34+
## :rotating_light: Important notice
35+
Franz 4 plugins are __not necessarily compatible__ with Franz 5. Please help us to port the [legacy recipes](https://github.com/meetfranz/plugins-legacy) recipes to Franz 5.

docs/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Franz Integration Documentation
2+
Create your own [Franz](http://meetfranz.com) service integration within a few minutes.
3+
4+
* [Overview / How to create a Franz integration](integration.md)
5+
* [Configuration (package.json)](configuration.md)
6+
* [Frontend API (webview.js)](frontend_api.md)
7+
* [Backend API (index.js)](backend_api.md)

docs/backend_api.md

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Backend API
2+
3+
Provides a set of helper functions to integrate the recipe into [Franz](http://meetfranz.com).
4+
5+
## Franz Backend Class Methods
6+
* [validateUrl](#user-content-validateurl)
7+
* [overrideUserAgent](#user-content-overrideuseragent)
8+
9+
## Events
10+
* [webview events](#user-content-events)
11+
12+
### validateUrl(URL)
13+
Validate if the given URL is a valid service instance.
14+
15+
#### Arguments
16+
1. `string` URL
17+
18+
#### Returns
19+
[`Promise`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)
20+
21+
#### Usage
22+
23+
```js
24+
// RocketChat integration
25+
module.exports = Franz => class RocketChat extends Franz {
26+
async validateUrl(url) {
27+
try {
28+
const resp = await window.fetch(`${url}/api/info`, {
29+
method: 'GET',
30+
headers: {
31+
'Content-Type': 'application/json',
32+
},
33+
});
34+
const data = await resp.json();
35+
36+
return Object.hasOwnProperty.call(data, 'version');
37+
} catch (err) {
38+
console.error(err);
39+
}
40+
41+
return false;
42+
}
43+
};
44+
```
45+
46+
### overrideUserAgent()
47+
Validate if the given URL is a valid service instance.
48+
49+
#### Returns
50+
`Boolean`
51+
52+
#### Usage
53+
54+
```js
55+
// Discord integration
56+
module.exports = Franz => class Discord extends Franz {
57+
overrideUserAgent() {
58+
const useragent = window.navigator.userAgent;
59+
60+
// Quick and dirty hackfix
61+
const parts = useragent.split('(KHTML, like Gecko)');
62+
63+
return parts.join('(KHTML, like Gecko) discord/0.0.248').replace('Electron', 'Discord').replace('Franz', 'Discord');
64+
}
65+
};
66+
67+
```
68+
69+
### Events
70+
Franz recipes can hook into the [electron webview events](https://electron.atom.io/docs/api/webview-tag/#dom-events) to trigger custom functions.
71+
72+
This is necessary for services like TweetDeck where custom URL forwarding is needed during login.
73+
74+
#### Usage
75+
```js
76+
module.exports = Franz => class Tweetdeck extends Franz {
77+
events = {
78+
'did-get-redirect-request': '_redirectFix',
79+
}
80+
81+
_redirectFix(event) {
82+
if (event.newURL !== undefined && event.oldURL !== undefined && event.isMainFrame) {
83+
if (event.isMainFrame) {
84+
setTimeout(() => this.send('redirect-url', event.newURL), 100);
85+
event.preventDefault();
86+
}
87+
}
88+
}
89+
};
90+
```

docs/configuration.md

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Integration Config
2+
3+
A [Franz](http://meetfranz.com) recipe is a node module. In order to learn more about node modules and their configuration check the official [Node.js documentation](https://nodejs.org/api/modules.html) / [npm package.json documentation](https://docs.npmjs.com/files/package.json).
4+
5+
## Table of Contents
6+
* [Config flags](#user-content-config-flags)
7+
* [Examples](#user-content-examples)
8+
9+
## Config flags
10+
11+
`string` **id**<br />
12+
Unique identifier name of the plugin. The name of the plugin folder has to be the same.
13+
14+
`string` **name**<br />
15+
Display name of the service.
16+
17+
`string` **version**<br />
18+
Version number. Will be used for auto updating the integrations. The version number must be in a semver compatible format: `1.0.0`.
19+
**important:** the version will be used to figure out if a new recipe update should be deployed to the user.
20+
21+
`string` **desciption**<br />
22+
Short description about your integration. Will be displayed in a future release.
23+
24+
`string` **main**<br />
25+
The plugins main entry point. In our case `index.js`.
26+
27+
`string` **author**<br />
28+
Author of the integration. Will be displayed in a future release.
29+
30+
`string` **license**<br />
31+
The license of the integration. We prefer MIT, but here is a list of all the available SPDX licenses http://spdx.org/licenses/
32+
33+
`object` **config**<br />
34+
This is the Franz specific integration config.
35+
36+
* `string` **serviceURL**<br/>
37+
Defines the URL that should be loaded into the Franz webview.
38+
<br /><br />
39+
If you want to load a simple URL like `https://www.messenger.com`, you can simply define it via the `serviceURL` parameter. If your service URL is team based, e.g. Slack or HipChat you can use `https://{teamID}.slack.com`.
40+
<br /><br />
41+
If your service works with custom URLs, just leave this empty.
42+
<br /><br />
43+
**Examples**
44+
```json
45+
{
46+
"serviceURL": "https://www.messenger.com"
47+
}
48+
```
49+
<br />
50+
```json
51+
{
52+
"serviceURL": "https://{teamID}.slack.com"
53+
}
54+
```
55+
* `boolean` **hasTeamID** _default: true_<br />
56+
Is this a team based service? If true, the interface to add the service will require a team identifier. e.g. `[teamID]`.slack.com
57+
* `boolean` **urlInputSuffix**<br />
58+
This option is only used in combination with `hasTeamId: true` in order to display the value of `urlInputSuffix` after the input for TeamId to make it obvious to the user what input is required from him. Eg. _&lt;TeamID&gt;.hipchat.com_
59+
* `boolean` **hasCustomUrl** _default: false_<br />
60+
On premise services like HipChat, Mattermost, ... require a custom URL. This option enables the user to enter a custom URL when adding the service.
61+
* `boolean` **hasNotificationSound** _default: false_<br />
62+
Some services provide their own notification sound. In order to avoid multiple sounds when the user receives a message set this to `true`. If the service has no built in notification sound set this to `false`.
63+
* `boolean` **hasIndirectMessages** _default: false_<br />
64+
Services like Slack or HipChat have direct messages e.g. a mention or message to every user in a channel (@channel) and indirect messages e.g. general discussion in a channel. If this flag is set to `true`, the user can enable/disable if there should be a badge for indirect messages.
65+
* `string` **message**<br />
66+
Info message that will be displayed in the add/edit service interface.
67+
68+
## Example
69+
### HipChat configuration
70+
```json
71+
{
72+
"id": "mattermost",
73+
"name": "Mattermost",
74+
"version": "1.0.0",
75+
"description": "Mattermost",
76+
"main": "index.js",
77+
"author": "Stefan Malzner <[email protected]>",
78+
"license": "MIT",
79+
"config": {
80+
"hasNotificationSound": true,
81+
"hasIndirectMessages": true,
82+
"hasCustomUrl": true
83+
}
84+
}
85+
```

docs/frontend_api.md

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Frontend API
2+
3+
Provides a set of helper functions to integrate the service into [Franz](http://meetfranz.com).
4+
5+
## Franz Class Methods
6+
* [setBadge](#user-content-setbadge)
7+
* [injectCSS](#user-content-injectcss)
8+
* [loop](#user-content-loop)
9+
10+
### setBadge(directMessages, [indirectMessages])
11+
Sets the unread message badge
12+
13+
#### Arguments
14+
1. `int` directMessages
15+
* sets the count of direct messages eg. Slack direct mentions, or a message to @channel
16+
2. `int` indirectMessages (optional)
17+
* Set a badge that defines there are new messages but they do not involve me directly to me eg. in a channel
18+
19+
#### Usage
20+
21+
```js
22+
Franz.setBadge(4, 2);
23+
```
24+
25+
### injectCSS(pathToCssFile)
26+
Injects the contents of one or more CSS files into the current webview
27+
28+
#### Arguments
29+
1. `string` cssFile
30+
* CSS files that should be injected. This must be an absolute path to the file
31+
32+
#### Usage
33+
34+
```js
35+
const path = require('path');
36+
37+
// inject a single css file
38+
Franz.injectCSS(path.join(__dirname, 'style.css'));
39+
40+
// inject multiple css files
41+
const globalStyles = path.join(__dirname, 'global.css');
42+
const focusModeStyles = path.join(__dirname, 'focusmode.css');
43+
44+
Franz.injectCSS(globalStyles, focusModeStyles);
45+
```
46+
47+
### loop(action)
48+
Runs an action every X milliseconds (Franz default is currently 1s)
49+
50+
#### Arguments
51+
1. `function` action
52+
53+
#### Usage
54+
55+
```js
56+
// slack integration
57+
const path = require('path');
58+
59+
module.exports = (Franz) => {
60+
const getMessages = () => {
61+
const directMessages = $('.unread_highlights, .unread_highlight').not('.hidden').length;
62+
const indirectMessages = $('.unread').length - directMessages;
63+
64+
Franz.setBadge(directMessages, indirectMessages);
65+
}
66+
67+
Franz.loop(getMessages);
68+
69+
Franz.injectCSS(path.join(__dirname, 'style.css'));
70+
}
71+
```

0 commit comments

Comments
 (0)