mirror of
https://github.com/mgerb/go-discord-bot
synced 2026-01-09 08:32:48 +00:00
UI done for video archiving
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import 'babel-polyfill';
|
||||
import './scss/index.scss';
|
||||
import { Provider } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
import { Clips, Downloader, NotFound, Oauth, Soundboard, Stats } from './pages';
|
||||
import { Clips, Downloader, NotFound, Oauth, Soundboard, Stats, VideoArchive } from './pages';
|
||||
import { rootStoreInstance } from './stores';
|
||||
import { Wrapper } from './wrapper';
|
||||
|
||||
@@ -18,6 +18,7 @@ const App: any = (): any => {
|
||||
<Route path="/clips" component={Clips} />
|
||||
<Route path="/oauth" component={Oauth} />
|
||||
<Route path="/stats" component={Stats} />
|
||||
<Route path="/video-archive" component={VideoArchive} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Wrapper>
|
||||
|
||||
15
client/app/components/embedded-youtube/embedded-youtube.scss
Normal file
15
client/app/components/embedded-youtube/embedded-youtube.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.embedded-youtube {
|
||||
overflow: hidden;
|
||||
padding-bottom: 56.25%;
|
||||
position: relative;
|
||||
height: 0;
|
||||
|
||||
&__iframe {
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
16
client/app/components/embedded-youtube/embedded-youtube.tsx
Normal file
16
client/app/components/embedded-youtube/embedded-youtube.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import './embedded-youtube.scss';
|
||||
|
||||
interface IProps {
|
||||
id: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const EmbeddedYoutube = ({ id, className }: IProps) => {
|
||||
const src = `https://www.youtube.com/embed/${id}`;
|
||||
return (
|
||||
<div className={`embedded-youtube ${className}`}>
|
||||
<iframe src={src} className="embedded-youtube__iframe" allowFullScreen />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-right: 20px;
|
||||
z-index: 100;
|
||||
|
||||
&__title-container {
|
||||
display: flex;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './embedded-youtube/embedded-youtube';
|
||||
export * from './header/header';
|
||||
export * from './navbar/navbar';
|
||||
export * from './sound-list/sound-list';
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
overflow-y: auto;
|
||||
padding-bottom: 10px;
|
||||
transition: 0.2s left ease-in-out;
|
||||
z-index: 100;
|
||||
|
||||
&--open {
|
||||
left: 0;
|
||||
|
||||
@@ -74,6 +74,7 @@ export class Navbar extends React.Component<Props, State> {
|
||||
return (
|
||||
<div className={'navbar ' + openClass}>
|
||||
{this.renderNavLink('Soundboard', '/', { exact: true })}
|
||||
{this.renderNavLink('Video Archive', '/video-archive')}
|
||||
{this.renderNavLink('Youtube Downloader', '/downloader')}
|
||||
{this.renderNavLink('Clips', '/clips')}
|
||||
{this.renderNavLink('Stats', '/stats')}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './claims';
|
||||
export * from './permissions';
|
||||
export * from './video-archive';
|
||||
|
||||
13
client/app/model/video-archive.ts
Normal file
13
client/app/model/video-archive.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export interface IVideoArchive {
|
||||
author: string;
|
||||
created_at: string;
|
||||
date_published: string;
|
||||
description: string;
|
||||
duration: number;
|
||||
id: number;
|
||||
title: string;
|
||||
updated_at: string;
|
||||
uploaded_by: string;
|
||||
url: string;
|
||||
youtube_id: string;
|
||||
}
|
||||
@@ -4,3 +4,4 @@ export * from './not-found/not-found';
|
||||
export * from './oauth/oauth';
|
||||
export * from './soundboard/soundboard';
|
||||
export * from './stats/stats';
|
||||
export * from './video-archive/video-archive';
|
||||
|
||||
14
client/app/pages/video-archive/video-archive.scss
Normal file
14
client/app/pages/video-archive/video-archive.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.video-archive {
|
||||
// custom card
|
||||
&__card {
|
||||
border-top-right-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
padding: 0 0 10px;
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
&__text-input {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
106
client/app/pages/video-archive/video-archive.tsx
Normal file
106
client/app/pages/video-archive/video-archive.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { EmbeddedYoutube } from '../../components';
|
||||
import { IVideoArchive, Permissions } from '../../model';
|
||||
import { ArchiveService } from '../../services/archive.service';
|
||||
import { AppStore } from '../../stores';
|
||||
import './video-archive.scss';
|
||||
|
||||
interface IProps {
|
||||
appStore: AppStore;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
archives: IVideoArchive[];
|
||||
url: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
@inject('appStore')
|
||||
@observer
|
||||
export class VideoArchive extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
archives: [],
|
||||
url: '',
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadArchives();
|
||||
}
|
||||
|
||||
async loadArchives() {
|
||||
const archives = await ArchiveService.getVideoArchive();
|
||||
if (archives) {
|
||||
this.setState({
|
||||
archives,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit = async (e: any) => {
|
||||
e.preventDefault();
|
||||
const { url } = this.state;
|
||||
this.setState({ error: undefined });
|
||||
|
||||
try {
|
||||
await ArchiveService.postVideoArchive({ url });
|
||||
} catch (e) {
|
||||
this.setState({ error: 'Invalid URL' });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ url: '' });
|
||||
this.loadArchives();
|
||||
};
|
||||
|
||||
renderForm() {
|
||||
const { error, url } = this.state;
|
||||
return (
|
||||
<form className="flex flex--v-center" onSubmit={this.onSubmit}>
|
||||
<input
|
||||
className="input video-archive__text-input"
|
||||
placeholder="Enter Youtube URL or ID..."
|
||||
value={url}
|
||||
onChange={e => this.setState({ url: e.target.value })}
|
||||
/>
|
||||
<input type="submit" className="button button--primary" style={{ marginLeft: '10px' }} />
|
||||
{error && (
|
||||
<span className="color__red" style={{ marginLeft: '5px' }}>
|
||||
{error}
|
||||
</span>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
renderArchives() {
|
||||
return this.state.archives.map((v, k) => (
|
||||
<div key={k} className="card video-archive__card test">
|
||||
<EmbeddedYoutube id={v.youtube_id} />
|
||||
<div style={{ padding: '10px 10px 0' }}>
|
||||
<h3 style={{ margin: '0 0 5px' }} className="ellipsis" title={v.title}>
|
||||
{v.title}
|
||||
</h3>
|
||||
<div>
|
||||
<span className="color__red">{v.uploaded_by}</span> -{' '}
|
||||
<small>{DateTime.fromISO(v.created_at).toLocaleString()}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { claims } = this.props.appStore;
|
||||
return (
|
||||
<div className="content">
|
||||
{claims && claims.permissions > Permissions.User && this.renderForm()}
|
||||
<div className="archive-grid">{this.renderArchives()}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
13
client/app/scss/grid.scss
Normal file
13
client/app/scss/grid.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.archive-grid {
|
||||
display: grid;
|
||||
grid-gap: 5px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
|
||||
|
||||
@include smallScreen() {
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
}
|
||||
|
||||
&__item {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
@import '~normalize.css/normalize.css';
|
||||
@import '~font-awesome/css/font-awesome.css';
|
||||
@import '~nprogress/nprogress.css';
|
||||
|
||||
@import './mixins.scss';
|
||||
@import './variables.scss';
|
||||
|
||||
@import './style.scss';
|
||||
|
||||
@import './button.scss';
|
||||
@import './card.scss';
|
||||
@import './input.scss';
|
||||
@import './grid.scss';
|
||||
@import './nprogress.scss';
|
||||
|
||||
14
client/app/scss/input.scss
Normal file
14
client/app/scss/input.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.input {
|
||||
line-height: 38px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $lightGray;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
height: 38px;
|
||||
background: $gray5;
|
||||
color: $white;
|
||||
|
||||
&::placeholder {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
@@ -3,3 +3,9 @@
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin smallScreen {
|
||||
@media only screen and (max-width: 768px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
5
client/app/scss/nprogress.scss
Normal file
5
client/app/scss/nprogress.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
// override nprogress css
|
||||
|
||||
#nprogress .bar {
|
||||
background: $red;
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
@import './variables.scss';
|
||||
@import './mixins.scss';
|
||||
|
||||
html {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
@@ -29,13 +26,16 @@ i {
|
||||
body {
|
||||
background-color: $gray1;
|
||||
color: $white;
|
||||
// padding-left: $navbarWidth;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex--v-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px;
|
||||
@include tinyScreen {
|
||||
@@ -43,16 +43,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
border-radius: 3px;
|
||||
border: 1px solid $lightGray;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
height: 30px;
|
||||
background: $gray5;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.column {
|
||||
flex: 1;
|
||||
|
||||
@@ -65,3 +55,19 @@ body {
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.color {
|
||||
&__red {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
&__primary {
|
||||
color: $primaryBlue;
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ $navbarWidth: 200px;
|
||||
|
||||
// colors
|
||||
$primaryBlue: #7289da;
|
||||
$red: #dd6e6e;
|
||||
$white: darken(white, 20%);
|
||||
|
||||
$gray1: #2e3136;
|
||||
|
||||
14
client/app/services/archive.service.ts
Normal file
14
client/app/services/archive.service.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as _ from 'lodash';
|
||||
import { IVideoArchive } from '../model';
|
||||
import { axios } from './axios.service';
|
||||
|
||||
export class ArchiveService {
|
||||
public static async getVideoArchive(): Promise<IVideoArchive[]> {
|
||||
const data = (await axios.get('/api/video-archive')).data.data;
|
||||
return _.orderBy(data, 'created_at', ['desc']);
|
||||
}
|
||||
|
||||
public static postVideoArchive(data: any): Promise<any> {
|
||||
return axios.post('/api/video-archive', data);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,29 @@
|
||||
import ax from 'axios';
|
||||
import nprogress from 'nprogress';
|
||||
|
||||
nprogress.configure({ showSpinner: false });
|
||||
|
||||
export const axios = ax.create();
|
||||
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
nprogress.start();
|
||||
// Do something before request is sent
|
||||
return config;
|
||||
},
|
||||
function(error) {
|
||||
error => {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
axios.interceptors.response.use(
|
||||
config => {
|
||||
nprogress.done();
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
nprogress.done();
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ const getScreenWidth = () => {
|
||||
};
|
||||
|
||||
const isMobileScreen = () => {
|
||||
return getScreenWidth() < 520;
|
||||
return getScreenWidth() < 768;
|
||||
};
|
||||
|
||||
export const Util = {
|
||||
|
||||
@@ -2,8 +2,6 @@ import { inject, observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router';
|
||||
import { Header, Navbar } from './components';
|
||||
//styling
|
||||
import './scss/index.scss';
|
||||
import { Util } from './util';
|
||||
import './wrapper.scss';
|
||||
|
||||
|
||||
68
client/package-lock.json
generated
68
client/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "go-discord-bot",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -24,11 +24,21 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.110.tgz",
|
||||
"integrity": "sha512-iXYLa6olt4tnsCA+ZXeP6eEW3tk1SulWeYyP/yooWfAtXjozqXgtX4+XUtMuOCfYjKGz3F34++qUc3Q+TJuIIw=="
|
||||
},
|
||||
"@types/luxon": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-1.2.2.tgz",
|
||||
"integrity": "sha512-JziyQbl0YIE36lVLDMLhkEhZ1h3Do/+H6x908tXRhzPFrcGAyh7mJ44rhDff+R230RaeIUKeWnhoB8lH5SdsPA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.4.tgz",
|
||||
"integrity": "sha512-YMLlzdeNnAyLrQew39IFRkMacAR5BqKGIEei9ZjdHsIZtv+ZWKYTu1i7QJhetxQ9ReXx8w5f+cixdHZG3zgMQA=="
|
||||
},
|
||||
"@types/nprogress": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.0.29.tgz",
|
||||
"integrity": "sha1-BgvVEAIqAF8YQCNAMNMTL7kZVHE="
|
||||
},
|
||||
"@types/query-string": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/query-string/-/query-string-6.1.0.tgz",
|
||||
@@ -351,6 +361,11 @@
|
||||
"uri-js": "3.0.2"
|
||||
}
|
||||
},
|
||||
"ajv-errors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz",
|
||||
"integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk="
|
||||
},
|
||||
"ajv-keywords": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz",
|
||||
@@ -527,14 +542,6 @@
|
||||
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
|
||||
},
|
||||
"async": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
|
||||
"integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
|
||||
"requires": {
|
||||
"lodash": "4.17.10"
|
||||
}
|
||||
},
|
||||
"async-each": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
|
||||
@@ -3948,17 +3955,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-text-webpack-plugin": {
|
||||
"version": "4.0.0-beta.0",
|
||||
"resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz",
|
||||
"integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==",
|
||||
"requires": {
|
||||
"async": "2.6.0",
|
||||
"loader-utils": "1.1.0",
|
||||
"schema-utils": "0.4.5",
|
||||
"webpack-sources": "1.1.0"
|
||||
}
|
||||
},
|
||||
"extract-zip": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz",
|
||||
@@ -5696,6 +5692,11 @@
|
||||
"yallist": "2.1.2"
|
||||
}
|
||||
},
|
||||
"luxon": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.3.3.tgz",
|
||||
"integrity": "sha512-3CM0jpS3mbHwWoPYprX1/Zsd5esni0LkhMfSiSY6xQ3/M3pnct3OPWbWkQdEEl9MO9593k6PvDn1DhxCkpuZEw=="
|
||||
},
|
||||
"macaddress": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz",
|
||||
@@ -5891,6 +5892,28 @@
|
||||
"dom-walk": "0.1.1"
|
||||
}
|
||||
},
|
||||
"mini-css-extract-plugin": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.2.tgz",
|
||||
"integrity": "sha512-ots7URQH4wccfJq9Ssrzu2+qupbncAce4TmTzunI9CIwlQMp2XI+WNUw6xWF6MMAGAm1cbUVINrSjATaVMyKXg==",
|
||||
"requires": {
|
||||
"loader-utils": "1.1.0",
|
||||
"schema-utils": "1.0.0",
|
||||
"webpack-sources": "1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"schema-utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
|
||||
"integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
|
||||
"requires": {
|
||||
"ajv": "6.4.0",
|
||||
"ajv-errors": "1.0.0",
|
||||
"ajv-keywords": "3.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
@@ -6292,6 +6315,11 @@
|
||||
"set-blocking": "2.0.0"
|
||||
}
|
||||
},
|
||||
"nprogress": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
|
||||
"integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E="
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "go-discord-bot",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"description": "Client for go-discord-bot",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=prod webpack -p --progress --colors",
|
||||
@@ -13,7 +13,9 @@
|
||||
"@types/chart.js": "^2.7.22",
|
||||
"@types/jwt-decode": "^2.2.1",
|
||||
"@types/lodash": "^4.14.110",
|
||||
"@types/luxon": "^1.2.2",
|
||||
"@types/node": "^10.3.4",
|
||||
"@types/nprogress": "0.0.29",
|
||||
"@types/query-string": "^6.1.0",
|
||||
"@types/react": "^16.4.1",
|
||||
"@types/react-chartjs-2": "^2.5.7",
|
||||
@@ -32,17 +34,19 @@
|
||||
"chart.js": "^2.7.2",
|
||||
"clean-webpack-plugin": "^0.1.14",
|
||||
"css-loader": "^0.28.11",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"favicons-webpack-plugin": "0.0.9",
|
||||
"file-loader": "^1.1.11",
|
||||
"font-awesome": "^4.7.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"lodash": "^4.17.10",
|
||||
"luxon": "^1.3.3",
|
||||
"mini-css-extract-plugin": "^0.4.2",
|
||||
"mobx": "^5.0.3",
|
||||
"mobx-react": "^5.2.5",
|
||||
"node-sass": "^4.9.0",
|
||||
"normalize.css": "^8.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"postcss-loader": "^2.1.5",
|
||||
"query-string": "^6.1.0",
|
||||
"react": "^16.4.1",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
||||
const path = require('path');
|
||||
@@ -29,17 +29,29 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
fallback: 'style-loader',
|
||||
use: ['css-loader', 'postcss-loader', 'sass-loader'],
|
||||
}),
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath: './.',
|
||||
},
|
||||
},
|
||||
'css-loader',
|
||||
// 'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
fallback: 'style-loader',
|
||||
use: ['css-loader'],
|
||||
}),
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath: './.',
|
||||
},
|
||||
},
|
||||
'css-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.woff2?$|\.ttf$|\.eot$|\.svg$/,
|
||||
@@ -66,10 +78,9 @@ module.exports = {
|
||||
verbose: true,
|
||||
allowExternal: true,
|
||||
}),
|
||||
new ExtractTextPlugin({
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[hash].css',
|
||||
disable: false,
|
||||
allChunks: true,
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"client_id": "",
|
||||
"client_secret": "",
|
||||
"redirect_uri": "https://localhost/oauth",
|
||||
"default_room_id": "",
|
||||
|
||||
"bot_prefix": "#",
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var session *discordgo.Session
|
||||
|
||||
// Start the bot
|
||||
func Start(token string) *discordgo.Session {
|
||||
// initialize connection
|
||||
@@ -25,13 +27,34 @@ func Start(token string) *discordgo.Session {
|
||||
return session
|
||||
}
|
||||
|
||||
// GetSession - get current discord session
|
||||
func GetSession() *discordgo.Session {
|
||||
return session
|
||||
}
|
||||
|
||||
// SendEmbeddedNotification - sends notification to default room
|
||||
func SendEmbeddedNotification(title, description string) {
|
||||
if session == nil || config.Config.DefaultRoomID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
embed := &discordgo.MessageEmbed{
|
||||
Color: 0x42adf4,
|
||||
Title: title,
|
||||
Description: description,
|
||||
}
|
||||
|
||||
session.ChannelMessageSendEmbed(config.Config.DefaultRoomID, embed)
|
||||
}
|
||||
|
||||
func addHandler(session *discordgo.Session, handler interface{}) {
|
||||
session.AddHandler(handler)
|
||||
}
|
||||
|
||||
func connect(token string) *discordgo.Session {
|
||||
// Create a new Discord session using the provided bot token.
|
||||
session, err := discordgo.New("Bot " + token)
|
||||
var err error
|
||||
session, err = discordgo.New("Bot " + token)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
|
||||
@@ -13,16 +13,17 @@ var (
|
||||
)
|
||||
|
||||
type configType struct {
|
||||
Token string `json:"token"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
BotPrefix string `json:"bot_prefix"` //prefix to use for bot commands
|
||||
AdminEmails []string `json:"admin_emails"`
|
||||
ModEmails []string `json:"mod_emails"`
|
||||
ServerAddr string `json:"server_addr"`
|
||||
JWTSecret string `json:"jwt_secret"`
|
||||
Logger bool `json:"logger"`
|
||||
Token string `json:"token"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
BotPrefix string `json:"bot_prefix"` //prefix to use for bot commands
|
||||
AdminEmails []string `json:"admin_emails"`
|
||||
ModEmails []string `json:"mod_emails"`
|
||||
ServerAddr string `json:"server_addr"`
|
||||
JWTSecret string `json:"jwt_secret"`
|
||||
Logger bool `json:"logger"`
|
||||
DefaultRoomID string `json:"default_room_id"`
|
||||
|
||||
// hard coded folder paths
|
||||
SoundsPath string
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mgerb/go-discord-bot/server/bot"
|
||||
"github.com/mgerb/go-discord-bot/server/db"
|
||||
"github.com/mgerb/go-discord-bot/server/webserver/middleware"
|
||||
"github.com/mgerb/go-discord-bot/server/webserver/model"
|
||||
@@ -13,11 +14,11 @@ import (
|
||||
|
||||
// AddVideoArchiveRoutes -
|
||||
func AddVideoArchiveRoutes(group *gin.RouterGroup) {
|
||||
group.GET("/video-archives", listVideoArchivesHandler)
|
||||
group.GET("/video-archive", listVideoArchivesHandler)
|
||||
|
||||
authGroup := group.Group("", middleware.AuthorizedJWT())
|
||||
authGroup.POST("/video-archives", middleware.AuthPermissions(middleware.PermMod), postVideoArchivesHandler)
|
||||
authGroup.DELETE("/video-archives/:id", middleware.AuthPermissions(middleware.PermAdmin), deleteVideoArchivesHandler)
|
||||
authGroup.POST("/video-archive", middleware.AuthPermissions(middleware.PermMod), postVideoArchivesHandler)
|
||||
authGroup.DELETE("/video-archive/:id", middleware.AuthPermissions(middleware.PermAdmin), deleteVideoArchivesHandler)
|
||||
}
|
||||
|
||||
func listVideoArchivesHandler(c *gin.Context) {
|
||||
@@ -100,5 +101,9 @@ func postVideoArchivesHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
hostURL := "[Click here to see the full archive!](http://" + c.Request.Host + "/video-archive)"
|
||||
youtubeURL := "https://youtu.be/" + videoArchive.YoutubeID
|
||||
bot.SendEmbeddedNotification(videoArchive.Title, "**"+videoArchive.UploadedBy+"** archived a new video:\n"+youtubeURL+"\n\n"+hostURL)
|
||||
|
||||
response.Success(c, "saved")
|
||||
}
|
||||
Reference in New Issue
Block a user