diff --git a/KitsuAPI.js b/KitsuAPI.js
new file mode 100644
index 0000000..ebf1e58
--- /dev/null
+++ b/KitsuAPI.js
@@ -0,0 +1,8 @@
+const { http } = require('powercord/webpack');
+
+module.exports = {
+ searchAnime (title) {
+ const url = `https://kitsu.io/api/edge/anime?filter[text]=${encodeURIComponent(title)}&page[limit]=5`;
+ return http.get(url).then(r => JSON.parse(r.text));
+ }
+};
diff --git a/Settings.jsx b/Settings.jsx
new file mode 100644
index 0000000..f3c2830
--- /dev/null
+++ b/Settings.jsx
@@ -0,0 +1,14 @@
+const { React } = require('powercord/webpack');
+const { SwitchItem } = require('powercord/components/settings');
+
+module.exports = ({ getSetting, toggleSetting }) => (
+
+ toggleSetting('nsfwFilter')}
+ >
+ Filter NSFW
+
+
+);
diff --git a/commands/index.js b/commands/index.js
new file mode 100644
index 0000000..57127a1
--- /dev/null
+++ b/commands/index.js
@@ -0,0 +1,7 @@
+require('fs')
+ .readdirSync(__dirname)
+ .filter(file => file !== 'index.js')
+ .forEach(filename => {
+ const moduleName = filename.split('.')[0];
+ exports[moduleName] = require(`${__dirname}/${filename}`);
+ });
diff --git a/components/AnimeModal.jsx b/components/AnimeModal.jsx
new file mode 100644
index 0000000..b69efb2
--- /dev/null
+++ b/components/AnimeModal.jsx
@@ -0,0 +1,117 @@
+const { React } = require('powercord/webpack');
+const { Button, Icon } = require('powercord/components');
+const { Modal } = require('powercord/components/modal');
+const { TextInput } = require('powercord/components/settings');
+const KitsuAPI = require('../KitsuAPI');
+
+class AnimeResult extends React.Component {
+ constructor () {
+ super();
+ this.state = { small: true };
+ }
+
+ handleClick () {
+ const { small } = this.state;
+ this.setState({ small: !small });
+ }
+
+ render () {
+ const { small } = this.state;
+ const { item } = this.props;
+ let height, cutoff, imgHeight, title, airingStatus;
+ const vid = item.youtubeVideoId ? : '';
+ if (small) {
+ height = '100px';
+ cutoff = 350;
+ imgHeight = '100px';
+ title = item.titles.en;
+ airingStatus = '';
+ } else {
+ height = vid === '' ? '250px' : '700px';
+ cutoff = 1000;
+ imgHeight = '250px';
+ title = `${item.titles.en || ''} ${item.titles.ja_jp || ''}${item.titles.en_jp ? ' (' + item.titles.en_jp + ')' : ''}`;
+ airingStatus = {item.status === 'current' ? 'Currently Airing' : 'Finished Airing'};
+ }
+ const synopsis = item.synopsis.length > cutoff ? `${item.synopsis.slice(0, cutoff - 6)}[...]` : item.synopsis;
+ const img = item.posterImage.medium ?
: '';
+ return (
+ this.handleClick() }
+ style={{ height }}
+ >
+
+ {img}
+
+
{title}
+
{synopsis}
+
+ {item.showType}
+ {item.ageRating || 'NR'}
+ {item.averageRating}%
+ {airingStatus}
+
+
+
+ {!small ? vid : ''}
+
+ );
+ }
+}
+
+module.exports = class AnimeModal extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = { entries: [],
+ textValue: ''
+ };
+ }
+
+ setText (t) {
+ this.setState({ textValue: t });
+ }
+
+ handleSearch () {
+ KitsuAPI.searchAnime(this.state.textValue).then((resp) => {
+ this.setState({ entries: resp.data });
+ });
+ }
+
+ render () {
+ const { entries } = this.state;
+ const animeResultList = [];
+ entries.forEach(animeResult => {
+ if (this.props.getSetting('nsfwFilter', true) && !animeResult.attributes.nsfw) {
+ animeResultList.push();
+ }
+ });
+ return (
+
+
+
+ Anime Search
+
+
+
+
+ this.setText(t)}
+ >
+ Title
+
+
+
+
+
+ {animeResultList}
+
+
+
+ );
+ }
+};
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..42e1350
--- /dev/null
+++ b/index.js
@@ -0,0 +1,47 @@
+const { Tooltip } = require('powercord/components');
+const { Plugin } = require('powercord/entities');
+const { open: openModal } = require('powercord/modal');
+const { inject, uninject } = require('powercord/injector');
+const { React, getModuleByDisplayName } = require('powercord/webpack');
+
+const { resolve } = require('path');
+
+const commands = require('./commands');
+const AnimeModal = require('./components/AnimeModal');
+const Settings = require('./Settings');
+
+module.exports = class Anime extends Plugin {
+ async startPlugin () {
+ this.loadCSS(resolve(__dirname, 'style.scss'));
+ this._injectModal();
+ this.registerSettings('anime', 'Anime Search', (props) =>
+ React.createElement(Settings, {
+ ...props
+ })
+ );
+
+ Object.values(commands).forEach(command =>
+ this.registerCommand(command.command, command.aliases || [], command.description, command.usage, command.func)
+ );
+ }
+
+ pluginWillUnload () {
+ uninject('anime-headerbar');
+ }
+
+ async _injectModal () {
+ const HeaderBarContainer = await getModuleByDisplayName('HeaderBarContainer');
+ inject('anime-headerbar', HeaderBarContainer.prototype, 'renderToolbar', (args, res) => {
+ res.props.children.push(
+ React.createElement(Tooltip, {
+ text: 'Anime lookup',
+ position: 'bottom'
+ }, React.createElement('div', {
+ className: 'anime-header-icon-s',
+ onClick: () => openModal(() => React.createElement(this.settings.connectStore(AnimeModal)))
+ }))
+ );
+ return res;
+ });
+ }
+};
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..687af3e
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "Anime",
+ "version": "1.0.0",
+ "description": "Anime lookup inside of Powercord",
+ "author": "CyberRonin",
+ "license": "MIT"
+}
diff --git a/style.scss b/style.scss
new file mode 100644
index 0000000..0b9a2a5
--- /dev/null
+++ b/style.scss
@@ -0,0 +1,103 @@
+.anime-header-icon {
+ &-s, &-a {
+ cursor: pointer;
+ height: 24px;
+ margin: 0 8px;
+ width: 24px;
+ opacity: .6;
+
+ &:hover {
+ opacity: .8;
+ }
+ }
+
+ &-a {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox='0 0 255 255'%3E%3Cpath fill='%23E75E45' d='M179.6,64.3c-6.8-2.5-14.1-4.1-21.8-4.4c-12.7-0.6-24.8,2.2-35.4,7.6c-0.6,0.3-1.3,0.6-2,1v36.4 c0,0.5,0,2.4-0.3,4c-0.7,3.7-2.9,7-6,9.1c-2.6,1.8-5.6,2.6-8.8,2.5c-0.6,0-1.3-0.1-1.9-0.2c-1.6-0.3-3.3-0.9-3.8-1.1 c-1.4-0.5-21.8-8.4-31.6-12.2c-1.2-0.5-2.2-0.9-3-1.2c-11.7,9.9-24,21.7-35.5,35.6c-0.1,0.1-0.6,0.7-0.7,0.8 c-1.5,2.1-1.6,5.1,0,7.4c1.2,1.7,3.1,2.7,5,2.8c1.3,0.1,2.7-0.3,3.9-1.1c0.1-0.1,0.2-0.2,0.4-0.3c12.2-8.8,25.6-15.9,39.8-21.6 c1-0.5,2.2-0.8,3.3-0.7c1.6,0.1,3.1,0.7,4.3,1.9c2.3,2.3,2.4,6,0.5,8.5c-0.8,1.2-1.5,2.4-2.2,3.6c-7.6,12.4-13.7,25.9-18.3,40 c-0.1,0.4-0.2,0.7-0.3,1.1v0.1c-0.4,1.7-0.1,3.5,1,5c1.2,1.7,3.1,2.7,5.1,2.8c1.4,0.1,2.7-0.3,3.9-1.1c0.5-0.4,1-0.8,1.4-1.3 c0.1-0.2,0.3-0.4,0.4-0.6c5-7.1,10.5-13.8,16.4-20c26.3-28.2,61.2-48.1,100.3-55.9c0.3-0.1,0.6-0.1,0.9-0.1c2.2,0.1,3.9,2,3.8,4.2 c-0.1,1.9-1.4,3.3-3.2,3.7c-36.3,7.7-101.7,50.8-78.8,113.4c0.4,1,0.7,1.6,1.2,2.5c1.2,1.7,3.1,2.7,5,2.8c1.1,0,4.2-0.3,6.1-3.7 c3.7-7,10.7-14.8,30.9-23.2c56.3-23.3,65.6-56.6,66.6-77.7v-1.2C227.1,102.1,207.6,74.7,179.6,64.3L179.6,64.3z M123.1,229.3 c-5.2-15.5-4.7-30.5,1.4-44.8c11.7,18.9,32.1,20.5,32.1,20.5C135.7,213.6,127.5,222.3,123.1,229.3z'%2F%3E%3Cpath fill='%23E75E45' d='M28,66.4c0.1,0.2,0.3,0.4,0.4,0.5c5.3,7.2,11.3,13.5,17.8,19.1c0.1,0.1,0.2,0.1,0.2,0.2 c4.2,3.6,12.2,8.8,18,10.9c0,0,36.1,13.9,38,14.7c0.7,0.3,1.7,0.6,2.2,0.7c1.6,0.3,3.3,0,4.8-1s2.4-2.5,2.7-4.1 c0.1-0.6,0.2-1.6,0.2-2.3V64.3c0.1-6.2-1.9-15.6-3.7-20.8c0-0.1-0.1-0.2-0.1-0.3c-2.8-8.1-6.6-16-11.4-23.5l-0.3-0.6L96.7,19 c-2-2.8-6-3.5-8.9-1.5c-0.5,0.3-0.8,0.7-1.2,1.1c-0.3,0.4-0.5,0.7-0.8,1.1c-6.4,9.3-9,20.6-7.3,31.7c-3.3,1.7-6.8,4-7.2,4.3 s-3.9,2.7-6.6,5.2c-9.7-5.5-21.3-7.2-32.2-4.6c-0.4,0.1-0.9,0.2-1.3,0.3c-0.5,0.2-1,0.4-1.4,0.7c-2.9,2-3.7,5.9-1.8,8.9 C28,66.2,28,66.4,28,66.4z M91.5,26.3c3.4,5.7,6.3,11.6,8.6,17.8c-4.6,0.8-9.1,2-13.5,3.6C86,40.2,87.7,32.8,91.5,26.3z M58.4,67.1c-3.2,3.5-5.9,7.3-8.3,11.3c-4.9-4.3-9.4-9.2-13.5-14.4C44.1,62.7,51.6,63.8,58.4,67.1z'%2F%3E%3C%2Fsvg%3E"); }
+
+ &-s {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox='0 0 255 255'%3E%3Cpath fill='%23E75E45' d='M179.6,64.3c-6.8-2.5-14.1-4.1-21.8-4.4c-12.7-0.6-24.8,2.2-35.4,7.6c-0.6,0.3-1.3,0.6-2,1v36.4 c0,0.5,0,2.4-0.3,4c-0.7,3.7-2.9,7-6,9.1c-2.6,1.8-5.6,2.6-8.8,2.5c-0.6,0-1.3-0.1-1.9-0.2c-1.6-0.3-3.3-0.9-3.8-1.1 c-1.4-0.5-21.8-8.4-31.6-12.2c-1.2-0.5-2.2-0.9-3-1.2c-11.7,9.9-24,21.7-35.5,35.6c-0.1,0.1-0.6,0.7-0.7,0.8 c-1.5,2.1-1.6,5.1,0,7.4c1.2,1.7,3.1,2.7,5,2.8c1.3,0.1,2.7-0.3,3.9-1.1c0.1-0.1,0.2-0.2,0.4-0.3c12.2-8.8,25.6-15.9,39.8-21.6 c1-0.5,2.2-0.8,3.3-0.7c1.6,0.1,3.1,0.7,4.3,1.9c2.3,2.3,2.4,6,0.5,8.5c-0.8,1.2-1.5,2.4-2.2,3.6c-7.6,12.4-13.7,25.9-18.3,40 c-0.1,0.4-0.2,0.7-0.3,1.1v0.1c-0.4,1.7-0.1,3.5,1,5c1.2,1.7,3.1,2.7,5.1,2.8c1.4,0.1,2.7-0.3,3.9-1.1c0.5-0.4,1-0.8,1.4-1.3 c0.1-0.2,0.3-0.4,0.4-0.6c5-7.1,10.5-13.8,16.4-20c26.3-28.2,61.2-48.1,100.3-55.9c0.3-0.1,0.6-0.1,0.9-0.1c2.2,0.1,3.9,2,3.8,4.2 c-0.1,1.9-1.4,3.3-3.2,3.7c-36.3,7.7-101.7,50.8-78.8,113.4c0.4,1,0.7,1.6,1.2,2.5c1.2,1.7,3.1,2.7,5,2.8c1.1,0,4.2-0.3,6.1-3.7 c3.7-7,10.7-14.8,30.9-23.2c56.3-23.3,65.6-56.6,66.6-77.7v-1.2C227.1,102.1,207.6,74.7,179.6,64.3L179.6,64.3z M123.1,229.3 c-5.2-15.5-4.7-30.5,1.4-44.8c11.7,18.9,32.1,20.5,32.1,20.5C135.7,213.6,127.5,222.3,123.1,229.3z'%2F%3E%3Cpath fill='%23E75E45' d='M28,66.4c0.1,0.2,0.3,0.4,0.4,0.5c5.3,7.2,11.3,13.5,17.8,19.1c0.1,0.1,0.2,0.1,0.2,0.2 c4.2,3.6,12.2,8.8,18,10.9c0,0,36.1,13.9,38,14.7c0.7,0.3,1.7,0.6,2.2,0.7c1.6,0.3,3.3,0,4.8-1s2.4-2.5,2.7-4.1 c0.1-0.6,0.2-1.6,0.2-2.3V64.3c0.1-6.2-1.9-15.6-3.7-20.8c0-0.1-0.1-0.2-0.1-0.3c-2.8-8.1-6.6-16-11.4-23.5l-0.3-0.6L96.7,19 c-2-2.8-6-3.5-8.9-1.5c-0.5,0.3-0.8,0.7-1.2,1.1c-0.3,0.4-0.5,0.7-0.8,1.1c-6.4,9.3-9,20.6-7.3,31.7c-3.3,1.7-6.8,4-7.2,4.3 s-3.9,2.7-6.6,5.2c-9.7-5.5-21.3-7.2-32.2-4.6c-0.4,0.1-0.9,0.2-1.3,0.3c-0.5,0.2-1,0.4-1.4,0.7c-2.9,2-3.7,5.9-1.8,8.9 C28,66.2,28,66.4,28,66.4z M91.5,26.3c3.4,5.7,6.3,11.6,8.6,17.8c-4.6,0.8-9.1,2-13.5,3.6C86,40.2,87.7,32.8,91.5,26.3z M58.4,67.1c-3.2,3.5-5.9,7.3-8.3,11.3c-4.9-4.3-9.4-9.2-13.5-14.4C44.1,62.7,51.6,63.8,58.4,67.1z'%2F%3E%3C%2Fsvg%3E"); }
+}
+
+.anime-modal {
+ &-search {
+ margin-top: 20px;
+ display: flex;
+ align-items: center;
+ position: sticky;
+ top: 20px;
+ background-color: rgba(54, 57, 63, .9);
+ > div {
+ flex: 1;
+
+ + button {
+ margin-left: 15px;
+ }
+ }
+
+ .pc-input {
+ height: 32px;
+ }
+
+ .pc-divider {
+ display: none;
+ }
+ }
+ &-header {
+ color: white;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+ &-results {
+ display: flex;
+ flex-direction: column;
+ }
+ &-result {
+ display: flex;
+ flex-direction: column;
+ padding: 4px;
+ border: 1px solid #2f3136;
+ border-radius: 4px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ color: white;
+
+ &-image {
+ border-radius: 4px;
+ }
+ &-details {
+ margin-left: 5px;
+ display: flex;
+ flex-direction: column;
+ }
+ &-tags {
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+ height: 100%;
+ }
+ &-title {
+ margin-bottom: 5px;
+ font-size: 1.1em;
+ }
+ &-tag {
+ padding: 4px;
+ background-color: #7289DA;
+ border-radius: 4px;
+ }
+ &-rating, &-tv-rating {
+ display: flex;
+ align-items: center;
+
+ &-icon {
+ height: 20px;
+ width: 20px;
+ margin-right: 5px;
+ }
+ }
+ }
+ &-result:hover {
+ background-color: #2f3136;
+ cursor: pointer;
+ }
+}
+