Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add Telegram Support #294

Merged
merged 1 commit into from
Jul 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/api/Ticker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface Ticker {
active: boolean
information: TickerInformation
twitter: TickerTwitter
telegram: TickerTelegram
location: TickerLocation
}

Expand All @@ -33,6 +34,17 @@ export interface TickerInformation {
facebook: string
}

export interface TickerTelegram {
active: boolean
bot_username: string
channel_name: string
}

export interface TickerTelegramFormData {
active: boolean
channel_name: string
}

export interface TickerTwitter {
active: boolean
connected: boolean
Expand Down Expand Up @@ -145,6 +157,17 @@ export function useTickerApi(token: string) {
}).then(response => response.json())
}

const putTickerTelegram = (
data: TickerTelegramFormData,
ticker: Ticker
): Promise<Response<TickerResponseData>> => {
return fetch(`${ApiUrl}/admin/tickers/${ticker.id}/telegram`, {
headers: headers,
body: JSON.stringify(data),
method: 'put',
}).then(response => response.json())
}

return {
deleteTicker,
deleteTickerUser,
Expand All @@ -156,5 +179,6 @@ export function useTickerApi(token: string) {
putTickerUsers,
putTickerReset,
putTickerTwitter,
putTickerTelegram,
}
}
65 changes: 65 additions & 0 deletions src/components/TelegramCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { FC } from 'react'
import { Button, Card, Container, Icon } from 'semantic-ui-react'
import { Ticker } from '../api/Ticker'
import TelegramModalForm from './TelegramModalForm'

interface Props {
ticker: Ticker
}

const TelegramCard: FC<Props> = ({ ticker }) => {
const telegram = ticker.telegram

return telegram.active ? (
<Container>
<Card fluid>
<Card.Content>
<Card.Header>
<Icon color="green" name="toggle on" />
{telegram.channel_name}
</Card.Header>
<Card.Meta>Bot: {telegram.bot_username}</Card.Meta>
</Card.Content>
<Card.Content extra>
<TelegramModalForm
ticker={ticker}
trigger={
<Button
color="blue"
compact
content="Configure"
icon="telegram"
size="tiny"
/>
}
/>
</Card.Content>
</Card>
</Container>
) : (
<Container>
<Card fluid>
<Card.Content>
You are currently not connected to Telegram. New messages will not be
published to your channel.
</Card.Content>
<Card.Content extra>
<TelegramModalForm
ticker={ticker}
trigger={
<Button
color="blue"
compact
content="Configure"
icon="telegram"
size="tiny"
/>
}
/>
</Card.Content>
</Card>
</Container>
)
}

export default TelegramCard
83 changes: 83 additions & 0 deletions src/components/TelegramForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React, { ChangeEvent, FC, FormEvent, useCallback } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { useQueryClient } from 'react-query'
import {
CheckboxProps,
Form,
InputOnChangeData,
Message,
} from 'semantic-ui-react'
import { Ticker, useTickerApi } from '../api/Ticker'
import useAuth from './useAuth'

interface Props {
callback: () => void
ticker: Ticker
}

interface FormValues {
active: boolean
channel_name: string
}

const TelegramForm: FC<Props> = ({ callback, ticker }) => {
const telegram = ticker.telegram
const { token } = useAuth()
const { putTickerTelegram } = useTickerApi(token)
const { handleSubmit, setValue } = useForm<FormValues>({
defaultValues: {
active: telegram.active,
channel_name: telegram.channel_name,
},
})
const queryClient = useQueryClient()

const onChange = useCallback(
(
e: ChangeEvent | FormEvent,
{ name, value, checked }: InputOnChangeData | CheckboxProps
) => {
if (checked !== undefined) {
setValue(name, checked)
} else {
setValue(name, value)
}
},
[setValue]
)

const onSubmit: SubmitHandler<FormValues> = data => {
putTickerTelegram(data, ticker).finally(() => {
queryClient.invalidateQueries(['ticker', ticker.id])
callback()
})
}

return (
<Form id="configureTelegram" onSubmit={handleSubmit(onSubmit)}>
<Message info size="small">
<Message.Header>Information</Message.Header>
<Message.Content>
Only public Telegram Channels are supported. The name of the Channel
is prefixed with an @ (e.g. @channel).
</Message.Content>
</Message>
<Form.Checkbox
defaultChecked={telegram.active}
label="Active"
name="active"
onChange={onChange}
toggle
/>
<Form.Input
defaultValue={telegram.channel_name}
label="Channel"
name="channel_name"
onChange={onChange}
required
/>
</Form>
)
}

export default TelegramForm
55 changes: 55 additions & 0 deletions src/components/TelegramModalForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { FC, useCallback, useState } from 'react'
import { Button, Modal } from 'semantic-ui-react'
import { Ticker } from '../api/Ticker'
import TelegramForm from './TelegramForm'

interface Props {
ticker: Ticker
trigger: React.ReactNode
}

const TelegramModalForm: FC<Props> = ({ ticker, trigger }) => {
const [open, setOpen] = useState<boolean>(false)

const handleClose = useCallback(() => {
setOpen(false)
}, [])

const handleOpen = useCallback(() => {
setOpen(true)
}, [])

return (
<Modal
closeIcon
onClose={handleClose}
onOpen={handleOpen}
open={open}
trigger={trigger}
>
<Modal.Header>Configure Telegram</Modal.Header>
<Modal.Content>
<TelegramForm callback={handleClose} ticker={ticker} />
</Modal.Content>
<Modal.Actions>
<Button.Group>
<Button
color="green"
content="Save"
form="configureTelegram"
type="submit"
/>
<Button.Or />
<Button
color="red"
content="Close"
onClick={handleClose}
type="button"
/>
</Button.Group>
</Modal.Actions>
</Modal>
)
}

export default TelegramModalForm
3 changes: 3 additions & 0 deletions src/views/TickerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useAuth from '../components/useAuth'
import TickerUsersCard from '../components/TickerUserCard'
import TickerResetModal from '../components/TickerResetModal'
import TwitterCard from '../components/TwitterCard'
import TelegramCard from '../components/TelegramCard'

interface TickerViewParams {
tickerId: string
Expand Down Expand Up @@ -56,6 +57,8 @@ const TickerView: FC = () => {
{ticker !== undefined && <TickerCard ticker={ticker} />}
<Header dividing>Twitter</Header>
<TwitterCard ticker={ticker} />
<Header dividing>Telegram</Header>
<TelegramCard ticker={ticker} />
{user?.roles.includes('admin') && (
<React.Fragment>
<Header dividing>Users</Header>
Expand Down