Deprecate Twitter #14
|
@ -87,21 +87,6 @@ query_mailaddr SELECT 1 FROM email WHERE ? IN (name || '@kibicara.example.com');
|
||||||
```
|
```
|
||||||
- Don't forget to restart OpenSMTPd when you change your database: `rcctl stop && rcctl start`
|
- Don't forget to restart OpenSMTPd when you change your database: `rcctl stop && rcctl start`
|
||||||
|
|
||||||
#### Configure Twitter
|
|
||||||
|
|
||||||
Twitter needs you to create a Twitter App, which hood admins can permit to read and write messages.
|
|
||||||
|
|
||||||
- Create Twitter account and app: https://developer.twitter.com
|
|
||||||
- Get your customer key and customer secret and append this to `/etc/kibicara.conf`:
|
|
||||||
```
|
|
||||||
[twitter]
|
|
||||||
consumer_key = '<your_consumer_key>'
|
|
||||||
consumer_secret = '<your_consumer_secret>'
|
|
||||||
```
|
|
||||||
- You need to configure a Callback Url in your Twitter App:
|
|
||||||
- Go to: `https://developer.twitter.com/en/apps`
|
|
||||||
- Add `https://kibicara.example.com/dashboard/twitter-callback` as Callback Url of your Twitter App. This is needed to successfully create a twitter oauth handshake.
|
|
||||||
|
|
||||||
#### Configure Telegram
|
#### Configure Telegram
|
||||||
Nothing to do, because telegram has a nice API.
|
Nothing to do, because telegram has a nice API.
|
||||||
|
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
|
|
||||||
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: 0BSD
|
|
||||||
|
|
||||||
from asyncio import CancelledError, gather, sleep
|
|
||||||
from logging import getLogger
|
|
||||||
|
|
||||||
from peony import PeonyClient, exceptions
|
|
||||||
|
|
||||||
from kibicara.config import config
|
|
||||||
from kibicara.platformapi import Censor, Message, Spawner
|
|
||||||
from kibicara.platforms.twitter.model import Twitter
|
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class TwitterBot(Censor):
|
|
||||||
def __init__(self, twitter_model):
|
|
||||||
super().__init__(twitter_model.hood)
|
|
||||||
self.twitter_model = twitter_model
|
|
||||||
self.enabled = self.twitter_model.enabled
|
|
||||||
self.polling_interval_sec = 60
|
|
||||||
self.mentions_since_id = self.twitter_model.mentions_since_id
|
|
||||||
self.dms_since_id = self.twitter_model.dms_since_id
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def destroy_hood(cls, hood):
|
|
||||||
"""Removes all its database entries."""
|
|
||||||
for twitter in await Twitter.objects.filter(hood=hood).all():
|
|
||||||
await twitter.delete()
|
|
||||||
|
|
||||||
async def run(self):
|
|
||||||
try:
|
|
||||||
if not self.twitter_model.verified:
|
|
||||||
raise ValueError("Oauth Handshake not completed")
|
|
||||||
self.client = PeonyClient(
|
|
||||||
consumer_key=config["twitter"]["consumer_key"],
|
|
||||||
consumer_secret=config["twitter"]["consumer_secret"],
|
|
||||||
access_token=self.twitter_model.access_token,
|
|
||||||
access_token_secret=self.twitter_model.access_token_secret,
|
|
||||||
)
|
|
||||||
if self.twitter_model.mentions_since_id is None:
|
|
||||||
logger.debug("since_id is None in model, fetch newest mention id")
|
|
||||||
await self._poll_mentions()
|
|
||||||
if self.twitter_model.dms_since_id is None:
|
|
||||||
logger.debug("since_id is None in model, fetch newest dm id")
|
|
||||||
await self._poll_direct_messages()
|
|
||||||
user = await self.client.user
|
|
||||||
if user.screen_name:
|
|
||||||
await self.twitter_model.update(username=user.screen_name)
|
|
||||||
logger.debug(
|
|
||||||
"Starting Twitter bot: {0}".format(self.twitter_model.__dict__)
|
|
||||||
)
|
|
||||||
await gather(self.poll(), self.push())
|
|
||||||
except CancelledError:
|
|
||||||
logger.debug(
|
|
||||||
"Bot {0} received Cancellation.".format(self.twitter_model.hood.name)
|
|
||||||
)
|
|
||||||
except exceptions.Unauthorized:
|
|
||||||
logger.debug(
|
|
||||||
"Bot {0} has invalid auth token.".format(self.twitter_model.hood.name)
|
|
||||||
)
|
|
||||||
await self.twitter_model.update(enabled=False)
|
|
||||||
self.enabled = self.twitter_model.enabled
|
|
||||||
except (KeyError, ValueError, exceptions.NotAuthenticated):
|
|
||||||
logger.warning("Missing consumer_keys for Twitter in your configuration.")
|
|
||||||
await self.twitter_model.update(enabled=False)
|
|
||||||
self.enabled = self.twitter_model.enabled
|
|
||||||
finally:
|
|
||||||
logger.debug("Bot {0} stopped.".format(self.twitter_model.hood.name))
|
|
||||||
|
|
||||||
async def poll(self):
|
|
||||||
while True:
|
|
||||||
dms = await self._poll_direct_messages()
|
|
||||||
logger.debug(
|
|
||||||
"Polled dms ({0}): {1}".format(self.twitter_model.hood.name, str(dms))
|
|
||||||
)
|
|
||||||
mentions = await self._poll_mentions()
|
|
||||||
logger.debug(
|
|
||||||
"Polled mentions ({0}): {1}".format(
|
|
||||||
self.twitter_model.hood.name, str(mentions)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
await self.twitter_model.update(
|
|
||||||
dms_since_id=self.dms_since_id, mentions_since_id=self.mentions_since_id
|
|
||||||
)
|
|
||||||
for message in dms:
|
|
||||||
await self.publish(Message(message))
|
|
||||||
for message_id, message in mentions:
|
|
||||||
await self.publish(Message(message, twitter_mention_id=message_id))
|
|
||||||
await sleep(self.polling_interval_sec)
|
|
||||||
|
|
||||||
async def _poll_direct_messages(self):
|
|
||||||
dms = await self.client.api.direct_messages.events.list.get()
|
|
||||||
dms = dms.events
|
|
||||||
# TODO check for next_cursor (see twitter api)
|
|
||||||
dms_filtered = []
|
|
||||||
if dms:
|
|
||||||
for dm in dms:
|
|
||||||
if int(dm.id) == self.dms_since_id:
|
|
||||||
break
|
|
||||||
dms_filtered.append(dm)
|
|
||||||
self.dms_since_id = int(dms[0].id)
|
|
||||||
messages = []
|
|
||||||
for dm in dms_filtered:
|
|
||||||
filtered_text = await self._filter_text(
|
|
||||||
dm.message_create.message_data.entities,
|
|
||||||
dm.message_create.message_data.text,
|
|
||||||
)
|
|
||||||
if not filtered_text:
|
|
||||||
continue
|
|
||||||
messages.append(filtered_text)
|
|
||||||
return messages
|
|
||||||
|
|
||||||
async def _poll_mentions(self):
|
|
||||||
mentions = await self.client.api.statuses.mentions_timeline.get(
|
|
||||||
since_id=self.mentions_since_id
|
|
||||||
)
|
|
||||||
if mentions:
|
|
||||||
self.mentions_since_id = mentions[0].id
|
|
||||||
messages = []
|
|
||||||
for mention in mentions:
|
|
||||||
filtered_text = await self._filter_text(mention.entities, mention.text)
|
|
||||||
if not filtered_text:
|
|
||||||
continue
|
|
||||||
messages.append((mention.id, filtered_text))
|
|
||||||
return messages
|
|
||||||
|
|
||||||
async def _filter_text(self, entities, text):
|
|
||||||
remove_indices = set()
|
|
||||||
for user in entities.user_mentions:
|
|
||||||
remove_indices.update(range(user.indices[0], user.indices[1] + 1))
|
|
||||||
for url in entities.urls:
|
|
||||||
remove_indices.update(range(url.indices[0], url.indices[1] + 1))
|
|
||||||
for symbol in entities.symbols:
|
|
||||||
remove_indices.update(range(symbol.indices[0], symbol.indices[1] + 1))
|
|
||||||
filtered_text = ""
|
|
||||||
for index, character in enumerate(text):
|
|
||||||
if index not in remove_indices:
|
|
||||||
filtered_text += character
|
|
||||||
return filtered_text.strip()
|
|
||||||
|
|
||||||
async def push(self):
|
|
||||||
while True:
|
|
||||||
message = await self.receive()
|
|
||||||
logger.debug(
|
|
||||||
"Received message from censor ({0}): {1}".format(
|
|
||||||
self.twitter_model.hood.name, message.text
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if hasattr(message, "twitter_mention_id"):
|
|
||||||
await self._retweet(message.twitter_mention_id)
|
|
||||||
else:
|
|
||||||
await self._post_tweet(message.text)
|
|
||||||
|
|
||||||
async def _post_tweet(self, message):
|
|
||||||
return await self.client.api.statuses.update.post(status=message)
|
|
||||||
|
|
||||||
async def _retweet(self, message_id):
|
|
||||||
return await self.client.api.statuses.retweet.post(id=message_id)
|
|
||||||
|
|
||||||
|
|
||||||
spawner = Spawner(Twitter, TwitterBot)
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
|
|
||||||
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: 0BSD
|
|
||||||
|
|
||||||
from ormantic import Boolean, ForeignKey, Integer, Model, Text
|
|
||||||
|
|
||||||
from kibicara.model import Hood, Mapping
|
|
||||||
|
|
||||||
|
|
||||||
class Twitter(Model):
|
|
||||||
id: Integer(primary_key=True) = None
|
|
||||||
hood: ForeignKey(Hood)
|
|
||||||
dms_since_id: Integer(allow_null=True) = None
|
|
||||||
mentions_since_id: Integer(allow_null=True) = None
|
|
||||||
access_token: Text()
|
|
||||||
access_token_secret: Text()
|
|
||||||
username: Text(allow_null=True) = None
|
|
||||||
verified: Boolean() = False
|
|
||||||
enabled: Boolean() = False
|
|
||||||
|
|
||||||
class Mapping(Mapping):
|
|
||||||
table_name = "twitterbots"
|
|
|
@ -1,183 +0,0 @@
|
||||||
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
|
|
||||||
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: 0BSD
|
|
||||||
|
|
||||||
from logging import getLogger
|
|
||||||
from sqlite3 import IntegrityError
|
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Response, status
|
|
||||||
from ormantic.exceptions import NoMatch
|
|
||||||
from peony.exceptions import NotAuthenticated
|
|
||||||
from peony.oauth_dance import get_access_token, get_oauth_token
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
from kibicara.config import config
|
|
||||||
from kibicara.platforms.twitter.bot import spawner
|
|
||||||
from kibicara.platforms.twitter.model import Twitter
|
|
||||||
from kibicara.webapi.hoods import get_hood, get_hood_unauthorized
|
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class BodyTwitterPublic(BaseModel):
|
|
||||||
username: str
|
|
||||||
|
|
||||||
|
|
||||||
async def get_twitter(twitter_id: int, hood=Depends(get_hood)):
|
|
||||||
try:
|
|
||||||
return await Twitter.objects.get(id=twitter_id, hood=hood)
|
|
||||||
except NoMatch:
|
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
|
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
twitter_callback_router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
|
||||||
"/public",
|
|
||||||
# TODO response_model,
|
|
||||||
operation_id="get_twitters_public",
|
|
||||||
)
|
|
||||||
async def twitter_read_all_public(hood=Depends(get_hood_unauthorized)):
|
|
||||||
twitterbots = await Twitter.objects.filter(hood=hood).all()
|
|
||||||
return [
|
|
||||||
BodyTwitterPublic(username=twitterbot.username)
|
|
||||||
for twitterbot in twitterbots
|
|
||||||
if twitterbot.verified == 1 and twitterbot.enabled == 1 and twitterbot.username
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
|
||||||
"/",
|
|
||||||
# TODO response_model,
|
|
||||||
operation_id="get_twitters",
|
|
||||||
)
|
|
||||||
async def twitter_read_all(hood=Depends(get_hood)):
|
|
||||||
return await Twitter.objects.filter(hood=hood).all()
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
|
||||||
"/{twitter_id}",
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="get_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_read(twitter=Depends(get_twitter)):
|
|
||||||
return twitter
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
|
||||||
"/{twitter_id}",
|
|
||||||
status_code=status.HTTP_204_NO_CONTENT,
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="delete_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_delete(twitter=Depends(get_twitter)):
|
|
||||||
spawner.stop(twitter)
|
|
||||||
await twitter.delete()
|
|
||||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
|
||||||
"/{twitter_id}/status",
|
|
||||||
status_code=status.HTTP_200_OK,
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="status_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_status(twitter=Depends(get_twitter)):
|
|
||||||
return {"status": spawner.get(twitter).status.name}
|
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
|
||||||
"/{twitter_id}/start",
|
|
||||||
status_code=status.HTTP_200_OK,
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="start_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_start(twitter=Depends(get_twitter)):
|
|
||||||
await twitter.update(enabled=True)
|
|
||||||
spawner.get(twitter).start()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
|
||||||
"/{twitter_id}/stop",
|
|
||||||
status_code=status.HTTP_200_OK,
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="stop_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_stop(twitter=Depends(get_twitter)):
|
|
||||||
await twitter.update(enabled=False)
|
|
||||||
spawner.get(twitter).stop()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
|
||||||
"/",
|
|
||||||
status_code=status.HTTP_201_CREATED,
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="create_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_create(response: Response, hood=Depends(get_hood)):
|
|
||||||
"""
|
|
||||||
`https://api.twitter.com/oauth/authorize?oauth_token=`
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Purge Twitter corpses
|
|
||||||
for corpse in await Twitter.objects.filter(hood=hood, verified=False).all():
|
|
||||||
await corpse.delete()
|
|
||||||
# Create Twitter
|
|
||||||
request_token = await get_oauth_token(
|
|
||||||
config["twitter"]["consumer_key"],
|
|
||||||
config["twitter"]["consumer_secret"],
|
|
||||||
callback_uri="{0}/dashboard/twitter-callback?hood={1}".format(
|
|
||||||
config["frontend_url"], hood.id
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if request_token["oauth_callback_confirmed"] != "true":
|
|
||||||
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE)
|
|
||||||
twitter = await Twitter.objects.create(
|
|
||||||
hood=hood,
|
|
||||||
access_token=request_token["oauth_token"],
|
|
||||||
access_token_secret=request_token["oauth_token_secret"],
|
|
||||||
)
|
|
||||||
response.headers["Location"] = str(twitter.id)
|
|
||||||
return twitter
|
|
||||||
except IntegrityError:
|
|
||||||
raise HTTPException(status_code=status.HTTP_409_CONFLICT)
|
|
||||||
except (KeyError, ValueError, NotAuthenticated):
|
|
||||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
||||||
|
|
||||||
|
|
||||||
@twitter_callback_router.get(
|
|
||||||
"/callback",
|
|
||||||
# TODO response_model
|
|
||||||
operation_id="callback_twitter",
|
|
||||||
)
|
|
||||||
async def twitter_read_callback(
|
|
||||||
oauth_token: str, oauth_verifier: str, hood=Depends(get_hood)
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
twitter = await Twitter.objects.filter(access_token=oauth_token).get()
|
|
||||||
access_token = await get_access_token(
|
|
||||||
config["twitter"]["consumer_key"],
|
|
||||||
config["twitter"]["consumer_secret"],
|
|
||||||
twitter.access_token,
|
|
||||||
twitter.access_token_secret,
|
|
||||||
oauth_verifier,
|
|
||||||
)
|
|
||||||
await twitter.update(
|
|
||||||
access_token=access_token["oauth_token"],
|
|
||||||
access_token_secret=access_token["oauth_token_secret"],
|
|
||||||
verified=True,
|
|
||||||
enabled=True,
|
|
||||||
)
|
|
||||||
spawner.start(twitter)
|
|
||||||
return {}
|
|
||||||
except IntegrityError:
|
|
||||||
raise HTTPException(status_code=status.HTTP_409_CONFLICT)
|
|
||||||
except NoMatch:
|
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
|
|
||||||
except (KeyError, ValueError, NotAuthenticated):
|
|
||||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
@ -16,8 +16,6 @@ from kibicara.platforms.email.webapi import router as email_router
|
||||||
from kibicara.platforms.telegram.webapi import router as telegram_router
|
from kibicara.platforms.telegram.webapi import router as telegram_router
|
||||||
from kibicara.platforms.test.webapi import router as test_router
|
from kibicara.platforms.test.webapi import router as test_router
|
||||||
from kibicara.platforms.mastodon.webapi import router as mastodon_router
|
from kibicara.platforms.mastodon.webapi import router as mastodon_router
|
||||||
from kibicara.platforms.twitter.webapi import router as twitter_router
|
|
||||||
from kibicara.platforms.twitter.webapi import twitter_callback_router
|
|
||||||
from kibicara.webapi.admin import router as admin_router
|
from kibicara.webapi.admin import router as admin_router
|
||||||
from kibicara.webapi.hoods import router as hoods_router
|
from kibicara.webapi.hoods import router as hoods_router
|
||||||
from kibicara.webapi.hoods.badwords import router as badwords_router
|
from kibicara.webapi.hoods.badwords import router as badwords_router
|
||||||
|
@ -35,12 +33,8 @@ hoods_router.include_router(test_router, prefix="/{hood_id}/test", tags=["test"]
|
||||||
hoods_router.include_router(
|
hoods_router.include_router(
|
||||||
telegram_router, prefix="/{hood_id}/telegram", tags=["telegram"]
|
telegram_router, prefix="/{hood_id}/telegram", tags=["telegram"]
|
||||||
)
|
)
|
||||||
hoods_router.include_router(
|
|
||||||
twitter_router, prefix="/{hood_id}/twitter", tags=["twitter"]
|
|
||||||
)
|
|
||||||
hoods_router.include_router(
|
hoods_router.include_router(
|
||||||
mastodon_router, prefix="/{hood_id}/mastodon", tags=["mastodon"]
|
mastodon_router, prefix="/{hood_id}/mastodon", tags=["mastodon"]
|
||||||
)
|
)
|
||||||
router.include_router(twitter_callback_router, prefix="/twitter", tags=["twitter"])
|
|
||||||
hoods_router.include_router(email_router, prefix="/{hood_id}/email", tags=["email"])
|
hoods_router.include_router(email_router, prefix="/{hood_id}/email", tags=["email"])
|
||||||
router.include_router(hoods_router, prefix="/hoods")
|
router.include_router(hoods_router, prefix="/hoods")
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { MastodonService } from './api/mastodon.service';
|
||||||
import { TelegramService } from './api/telegram.service';
|
import { TelegramService } from './api/telegram.service';
|
||||||
import { TestService } from './api/test.service';
|
import { TestService } from './api/test.service';
|
||||||
import { TriggersService } from './api/triggers.service';
|
import { TriggersService } from './api/triggers.service';
|
||||||
import { TwitterService } from './api/twitter.service';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [],
|
imports: [],
|
||||||
|
|
|
@ -14,6 +14,4 @@ export * from './test.service';
|
||||||
import { TestService } from './test.service';
|
import { TestService } from './test.service';
|
||||||
export * from './triggers.service';
|
export * from './triggers.service';
|
||||||
import { TriggersService } from './triggers.service';
|
import { TriggersService } from './triggers.service';
|
||||||
export * from './twitter.service';
|
export const APIS = [AdminService, BadwordsService, EmailService, HoodsService, MastodonService, TelegramService, TestService, TriggersService];
|
||||||
import { TwitterService } from './twitter.service';
|
|
||||||
export const APIS = [AdminService, BadwordsService, EmailService, HoodsService, MastodonService, TelegramService, TestService, TriggersService, TwitterService];
|
|
||||||
|
|
|
@ -1,595 +0,0 @@
|
||||||
/**
|
|
||||||
* FastAPI
|
|
||||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:no-unused-variable member-ordering */
|
|
||||||
|
|
||||||
import { Inject, Injectable, Optional } from '@angular/core';
|
|
||||||
import { HttpClient, HttpHeaders, HttpParams,
|
|
||||||
HttpResponse, HttpEvent, HttpParameterCodec } from '@angular/common/http';
|
|
||||||
import { CustomHttpParameterCodec } from '../encoder';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
import { HTTPValidationError } from '../model/models';
|
|
||||||
|
|
||||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
|
||||||
import { Configuration } from '../configuration';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class TwitterService {
|
|
||||||
|
|
||||||
protected basePath = 'http://localhost/api';
|
|
||||||
public defaultHeaders = new HttpHeaders();
|
|
||||||
public configuration = new Configuration();
|
|
||||||
public encoder: HttpParameterCodec;
|
|
||||||
|
|
||||||
constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
|
|
||||||
if (configuration) {
|
|
||||||
this.configuration = configuration;
|
|
||||||
}
|
|
||||||
if (typeof this.configuration.basePath !== 'string') {
|
|
||||||
if (typeof basePath !== 'string') {
|
|
||||||
basePath = this.basePath;
|
|
||||||
}
|
|
||||||
this.configuration.basePath = basePath;
|
|
||||||
}
|
|
||||||
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
|
|
||||||
if (typeof value === "object" && value instanceof Date === false) {
|
|
||||||
httpParams = this.addToHttpParamsRecursive(httpParams, value);
|
|
||||||
} else {
|
|
||||||
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
|
|
||||||
}
|
|
||||||
return httpParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
|
|
||||||
if (value == null) {
|
|
||||||
return httpParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value === "object") {
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
|
|
||||||
} else if (value instanceof Date) {
|
|
||||||
if (key != null) {
|
|
||||||
httpParams = httpParams.append(key,
|
|
||||||
(value as Date).toISOString().substr(0, 10));
|
|
||||||
} else {
|
|
||||||
throw Error("key may not be null if value is Date");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
|
|
||||||
httpParams, value[k], key != null ? `${key}.${k}` : k));
|
|
||||||
}
|
|
||||||
} else if (key != null) {
|
|
||||||
httpParams = httpParams.append(key, value);
|
|
||||||
} else {
|
|
||||||
throw Error("key may not be null if value is not object or array");
|
|
||||||
}
|
|
||||||
return httpParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Read Callback
|
|
||||||
* @param oauthToken
|
|
||||||
* @param oauthVerifier
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (oauthToken === null || oauthToken === undefined) {
|
|
||||||
throw new Error('Required parameter oauthToken was null or undefined when calling callbackTwitter.');
|
|
||||||
}
|
|
||||||
if (oauthVerifier === null || oauthVerifier === undefined) {
|
|
||||||
throw new Error('Required parameter oauthVerifier was null or undefined when calling callbackTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling callbackTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let queryParameters = new HttpParams({encoder: this.encoder});
|
|
||||||
if (oauthToken !== undefined && oauthToken !== null) {
|
|
||||||
queryParameters = this.addToHttpParams(queryParameters,
|
|
||||||
<any>oauthToken, 'oauth_token');
|
|
||||||
}
|
|
||||||
if (oauthVerifier !== undefined && oauthVerifier !== null) {
|
|
||||||
queryParameters = this.addToHttpParams(queryParameters,
|
|
||||||
<any>oauthVerifier, 'oauth_verifier');
|
|
||||||
}
|
|
||||||
if (hoodId !== undefined && hoodId !== null) {
|
|
||||||
queryParameters = this.addToHttpParams(queryParameters,
|
|
||||||
<any>hoodId, 'hood_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${this.configuration.basePath}/api/twitter/callback`,
|
|
||||||
{
|
|
||||||
params: queryParameters,
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Create
|
|
||||||
* `https://api.twitter.com/oauth/authorize?oauth_token=`
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public createTwitter(hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public createTwitter(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public createTwitter(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public createTwitter(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling createTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.post<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/`,
|
|
||||||
null,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Delete
|
|
||||||
* @param twitterId
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public deleteTwitter(twitterId: number, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public deleteTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public deleteTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public deleteTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (twitterId === null || twitterId === undefined) {
|
|
||||||
throw new Error('Required parameter twitterId was null or undefined when calling deleteTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling deleteTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.delete<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}`,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Read
|
|
||||||
* @param twitterId
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public getTwitter(twitterId: number, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public getTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public getTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public getTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (twitterId === null || twitterId === undefined) {
|
|
||||||
throw new Error('Required parameter twitterId was null or undefined when calling getTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling getTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}`,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Read All
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public getTwitters(hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public getTwitters(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public getTwitters(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public getTwitters(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling getTwitters.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/`,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Read All Public
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public getTwittersPublic(hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public getTwittersPublic(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public getTwittersPublic(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public getTwittersPublic(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling getTwittersPublic.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/public`,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Start
|
|
||||||
* @param twitterId
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public startTwitter(twitterId: number, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public startTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public startTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public startTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (twitterId === null || twitterId === undefined) {
|
|
||||||
throw new Error('Required parameter twitterId was null or undefined when calling startTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling startTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.post<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/start`,
|
|
||||||
null,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Status
|
|
||||||
* @param twitterId
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public statusTwitter(twitterId: number, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public statusTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public statusTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public statusTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (twitterId === null || twitterId === undefined) {
|
|
||||||
throw new Error('Required parameter twitterId was null or undefined when calling statusTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling statusTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/status`,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Twitter Stop
|
|
||||||
* @param twitterId
|
|
||||||
* @param hoodId
|
|
||||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
|
||||||
* @param reportProgress flag to report request and response progress.
|
|
||||||
*/
|
|
||||||
public stopTwitter(twitterId: number, hoodId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<any>;
|
|
||||||
public stopTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpResponse<any>>;
|
|
||||||
public stopTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable<HttpEvent<any>>;
|
|
||||||
public stopTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable<any> {
|
|
||||||
if (twitterId === null || twitterId === undefined) {
|
|
||||||
throw new Error('Required parameter twitterId was null or undefined when calling stopTwitter.');
|
|
||||||
}
|
|
||||||
if (hoodId === null || hoodId === undefined) {
|
|
||||||
throw new Error('Required parameter hoodId was null or undefined when calling stopTwitter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers = this.defaultHeaders;
|
|
||||||
|
|
||||||
let credential: string | undefined;
|
|
||||||
// authentication (OAuth2PasswordBearer) required
|
|
||||||
credential = this.configuration.lookupCredential('OAuth2PasswordBearer');
|
|
||||||
if (credential) {
|
|
||||||
headers = headers.set('Authorization', 'Bearer ' + credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
|
||||||
if (httpHeaderAcceptSelected === undefined) {
|
|
||||||
// to determine the Accept header
|
|
||||||
const httpHeaderAccepts: string[] = [
|
|
||||||
'application/json'
|
|
||||||
];
|
|
||||||
httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
||||||
}
|
|
||||||
if (httpHeaderAcceptSelected !== undefined) {
|
|
||||||
headers = headers.set('Accept', httpHeaderAcceptSelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let responseType: 'text' | 'json' = 'json';
|
|
||||||
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
|
|
||||||
responseType = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.post<any>(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/stop`,
|
|
||||||
null,
|
|
||||||
{
|
|
||||||
responseType: <any>responseType,
|
|
||||||
withCredentials: this.configuration.withCredentials,
|
|
||||||
headers: headers,
|
|
||||||
observe: observe,
|
|
||||||
reportProgress: reportProgress
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -49,8 +49,8 @@
|
||||||
<p>
|
<p>
|
||||||
<strong>Share the hood page: </strong> Just send the link to your hood
|
<strong>Share the hood page: </strong> Just send the link to your hood
|
||||||
page to your community. We also recommend to link it in your platform
|
page to your community. We also recommend to link it in your platform
|
||||||
account description (e.g. Twitter description) to give the users
|
account description (e.g. Mastodon account description) to give the
|
||||||
context and more information.
|
users context and more information.
|
||||||
</p>
|
</p>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
|
|
||||||
<div class="platforms-container">
|
<div class="platforms-container">
|
||||||
<app-email-settings [hoodId]="hoodId"></app-email-settings>
|
<app-email-settings [hoodId]="hoodId"></app-email-settings>
|
||||||
<app-twitter-settings [hoodId]="hoodId"></app-twitter-settings>
|
|
||||||
<app-telegram-settings [hoodId]="hoodId"></app-telegram-settings>
|
<app-telegram-settings [hoodId]="hoodId"></app-telegram-settings>
|
||||||
<app-mastodon-settings [hoodId]="hoodId"></app-mastodon-settings>
|
<app-mastodon-settings [hoodId]="hoodId"></app-mastodon-settings>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { DashboardComponent } from './dashboard.component';
|
||||||
import { HoodsComponent } from './hoods/hoods.component';
|
import { HoodsComponent } from './hoods/hoods.component';
|
||||||
import { AuthGuard } from '../core/auth/auth.guard';
|
import { AuthGuard } from '../core/auth/auth.guard';
|
||||||
import { BoardComponent } from './board/board.component';
|
import { BoardComponent } from './board/board.component';
|
||||||
import { TwitterCallbackComponent } from '../platforms/twitter/twitter-callback/twitter-callback.component';
|
|
||||||
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
import { AccountSettingsComponent } from './account-settings/account-settings.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
@ -15,8 +14,6 @@ const routes: Routes = [
|
||||||
{ path: '', component: HoodsComponent },
|
{ path: '', component: HoodsComponent },
|
||||||
{ path: 'hoods/:id', component: BoardComponent },
|
{ path: 'hoods/:id', component: BoardComponent },
|
||||||
{ path: 'settings', component: AccountSettingsComponent },
|
{ path: 'settings', component: AccountSettingsComponent },
|
||||||
// Platform-specific Routes
|
|
||||||
{ path: 'twitter-callback', component: TwitterCallbackComponent },
|
|
||||||
],
|
],
|
||||||
canActivate: [AuthGuard],
|
canActivate: [AuthGuard],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<h2>Platforms - choose one, get all hood messages</h2>
|
<h2>Platforms - choose one, get all hood messages</h2>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<app-twitter-bot-card [hoodId]="hoodId"></app-twitter-bot-card>
|
|
||||||
<app-telegram-bot-card [hoodId]="hoodId"></app-telegram-bot-card>
|
<app-telegram-bot-card [hoodId]="hoodId"></app-telegram-bot-card>
|
||||||
<app-email-bot-card [hoodId]="hoodId"></app-email-bot-card>
|
<app-email-bot-card [hoodId]="hoodId"></app-email-bot-card>
|
||||||
<app-mastodon-bot-card [hoodId]="hoodId"></app-mastodon-bot-card>
|
<app-mastodon-bot-card [hoodId]="hoodId"></app-mastodon-bot-card>
|
||||||
|
|
|
@ -2,22 +2,16 @@ import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { TelegramSettingsComponent } from './telegram/telegram-settings/telegram-settings.component';
|
import { TelegramSettingsComponent } from './telegram/telegram-settings/telegram-settings.component';
|
||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { TwitterSettingsComponent } from './twitter/twitter-settings/twitter-settings.component';
|
|
||||||
import { EmailSettingsComponent } from './email/email-settings/email-settings.component';
|
import { EmailSettingsComponent } from './email/email-settings/email-settings.component';
|
||||||
import { EmailDialogComponent } from './email/email-settings/email-dialog/email-dialog.component';
|
import { EmailDialogComponent } from './email/email-settings/email-dialog/email-dialog.component';
|
||||||
import { EmailInfoDialogComponent } from './email/email-settings/email-info-dialog/email-info-dialog.component';
|
import { EmailInfoDialogComponent } from './email/email-settings/email-info-dialog/email-info-dialog.component';
|
||||||
import { TelegramInfoDialogComponent } from './telegram/telegram-settings/telegram-info-dialog/telegram-info-dialog.component';
|
import { TelegramInfoDialogComponent } from './telegram/telegram-settings/telegram-info-dialog/telegram-info-dialog.component';
|
||||||
import { TelegramDialogComponent } from './telegram/telegram-settings/telegram-dialog/telegram-dialog.component';
|
import { TelegramDialogComponent } from './telegram/telegram-settings/telegram-dialog/telegram-dialog.component';
|
||||||
import { TwitterInfoDialogComponent } from './twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component';
|
|
||||||
import { TwitterCallbackComponent } from './twitter/twitter-callback/twitter-callback.component';
|
|
||||||
import { TwitterCorpsesPipe } from './twitter/twitter-corpses-pipe/twitter-corpses.pipe';
|
|
||||||
import { PlatformsInfoPageComponent } from './platforms-info-page/platforms-info-page.component';
|
import { PlatformsInfoPageComponent } from './platforms-info-page/platforms-info-page.component';
|
||||||
import { EmailBotCardComponent } from './email/email-bot-card/email-bot-card.component';
|
import { EmailBotCardComponent } from './email/email-bot-card/email-bot-card.component';
|
||||||
import { TelegramBotCardComponent } from './telegram/telegram-bot-card/telegram-bot-card.component';
|
import { TelegramBotCardComponent } from './telegram/telegram-bot-card/telegram-bot-card.component';
|
||||||
import { TwitterBotCardComponent } from './twitter/twitter-bot-card/twitter-bot-card.component';
|
|
||||||
import { EmailBotInfoDialogComponent } from './email/email-bot-card/email-bot-info-dialog/email-bot-info-dialog.component';
|
import { EmailBotInfoDialogComponent } from './email/email-bot-card/email-bot-info-dialog/email-bot-info-dialog.component';
|
||||||
import { TelegramBotInfoDialogComponent } from './telegram/telegram-bot-card/telegram-bot-info-dialog/telegram-bot-info-dialog.component';
|
import { TelegramBotInfoDialogComponent } from './telegram/telegram-bot-card/telegram-bot-info-dialog/telegram-bot-info-dialog.component';
|
||||||
import { TwitterBotInfoDialogComponent } from './twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component';
|
|
||||||
import { EmailConfirmationComponent } from './email/email-confirmation/email-confirmation.component';
|
import { EmailConfirmationComponent } from './email/email-confirmation/email-confirmation.component';
|
||||||
import { EmailUnsubscribeComponent } from './email/email-unsubscribe/email-unsubscribe.component';
|
import { EmailUnsubscribeComponent } from './email/email-unsubscribe/email-unsubscribe.component';
|
||||||
import { MastodonBotCardComponent } from './mastodon/mastodon-bot-card/mastodon-bot-card.component';
|
import { MastodonBotCardComponent } from './mastodon/mastodon-bot-card/mastodon-bot-card.component';
|
||||||
|
@ -28,22 +22,16 @@ import { MastodonBotInfoDialogComponent } from './mastodon/mastodon-bot-card/mas
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
TelegramSettingsComponent,
|
TelegramSettingsComponent,
|
||||||
TwitterSettingsComponent,
|
|
||||||
EmailSettingsComponent,
|
EmailSettingsComponent,
|
||||||
EmailDialogComponent,
|
EmailDialogComponent,
|
||||||
EmailInfoDialogComponent,
|
EmailInfoDialogComponent,
|
||||||
TelegramInfoDialogComponent,
|
TelegramInfoDialogComponent,
|
||||||
TelegramDialogComponent,
|
TelegramDialogComponent,
|
||||||
TwitterInfoDialogComponent,
|
|
||||||
TwitterCallbackComponent,
|
|
||||||
TwitterCorpsesPipe,
|
|
||||||
PlatformsInfoPageComponent,
|
PlatformsInfoPageComponent,
|
||||||
EmailBotCardComponent,
|
EmailBotCardComponent,
|
||||||
TelegramBotCardComponent,
|
TelegramBotCardComponent,
|
||||||
TwitterBotCardComponent,
|
|
||||||
EmailBotInfoDialogComponent,
|
EmailBotInfoDialogComponent,
|
||||||
TelegramBotInfoDialogComponent,
|
TelegramBotInfoDialogComponent,
|
||||||
TwitterBotInfoDialogComponent,
|
|
||||||
EmailConfirmationComponent,
|
EmailConfirmationComponent,
|
||||||
EmailUnsubscribeComponent,
|
EmailUnsubscribeComponent,
|
||||||
MastodonBotCardComponent,
|
MastodonBotCardComponent,
|
||||||
|
@ -55,7 +43,6 @@ import { MastodonBotInfoDialogComponent } from './mastodon/mastodon-bot-card/mas
|
||||||
exports: [
|
exports: [
|
||||||
TelegramSettingsComponent,
|
TelegramSettingsComponent,
|
||||||
MastodonSettingsComponent,
|
MastodonSettingsComponent,
|
||||||
TwitterSettingsComponent,
|
|
||||||
EmailSettingsComponent,
|
EmailSettingsComponent,
|
||||||
PlatformsInfoPageComponent,
|
PlatformsInfoPageComponent,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<div *ngIf="twitters$ | loading | async as twitters">
|
|
||||||
<ng-template [ngIf]="twitters.value">
|
|
||||||
<mat-card appearance="outlined">
|
|
||||||
<mat-card-header>
|
|
||||||
<div mat-card-avatar class="twitter"></div>
|
|
||||||
<mat-card-title class="platform-title">
|
|
||||||
Twitter
|
|
||||||
<button mat-icon-button aria-label="How to use">
|
|
||||||
<mat-icon
|
|
||||||
matTooltip="How to send and receive hood broadcast messages with twitter"
|
|
||||||
class="info-button"
|
|
||||||
(click)="onInfoClick()"
|
|
||||||
>info</mat-icon
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</mat-card-title>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content *ngIf="twitters.value.length !== 0; else noTwitter">
|
|
||||||
<mat-selection-list [multiple]="false" class="list">
|
|
||||||
<a
|
|
||||||
*ngFor="let twitter of twitters.value"
|
|
||||||
href="https://twitter.com/{{ twitter.username }}"
|
|
||||||
routerLinkActive="router-link-active"
|
|
||||||
>
|
|
||||||
<mat-list-option>
|
|
||||||
@{{ twitter.username }}
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</mat-list-option>
|
|
||||||
</a>
|
|
||||||
</mat-selection-list>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
<ng-template #noTwitter>
|
|
||||||
<mat-card-content>
|
|
||||||
Unfortunately your hood admin has not configured Twitter as platform
|
|
||||||
yet.
|
|
||||||
</mat-card-content>
|
|
||||||
</ng-template>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template [ngIf]="twitters.error"
|
|
||||||
><mat-icon class="warning">warning</mat-icon></ng-template
|
|
||||||
>
|
|
||||||
<ng-template [ngIf]="twitters.loading">
|
|
||||||
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
|
|
||||||
</ng-template>
|
|
||||||
</div>
|
|
|
@ -1,11 +0,0 @@
|
||||||
.twitter {
|
|
||||||
background-image: url("../../../../assets/twitter.png");
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-title {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 40px;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { TwitterBotCardComponent } from './twitter-bot-card.component';
|
|
||||||
|
|
||||||
describe('TwitterBotCardComponent', () => {
|
|
||||||
let component: TwitterBotCardComponent;
|
|
||||||
let fixture: ComponentFixture<TwitterBotCardComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [TwitterBotCardComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(TwitterBotCardComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
|
||||||
import { TwitterService } from 'src/app/core/api';
|
|
||||||
import { TwitterBotInfoDialogComponent } from './twitter-bot-info-dialog/twitter-bot-info-dialog.component';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-twitter-bot-card',
|
|
||||||
templateUrl: './twitter-bot-card.component.html',
|
|
||||||
styleUrls: ['./twitter-bot-card.component.scss'],
|
|
||||||
})
|
|
||||||
export class TwitterBotCardComponent implements OnInit {
|
|
||||||
@Input() hoodId;
|
|
||||||
twitters$;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private twitterService: TwitterService,
|
|
||||||
private dialog: MatDialog
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.twitters$ = this.twitterService.getTwittersPublic(this.hoodId);
|
|
||||||
}
|
|
||||||
|
|
||||||
onInfoClick() {
|
|
||||||
this.dialog.open(TwitterBotInfoDialogComponent);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
<mat-dialog-content>
|
|
||||||
<div class="container">
|
|
||||||
<h2>How to communicate with the hood via Twitter?</h2>
|
|
||||||
<mat-accordion>
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title
|
|
||||||
>How to subscribe to the hood via Twitter?</mat-panel-title
|
|
||||||
>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<p>
|
|
||||||
Click on the twitter bot name that is shown in the twitter card. Just
|
|
||||||
follow the twitter account that the link leads to.
|
|
||||||
</p>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title
|
|
||||||
>How to send a broadcast message to the hood?</mat-panel-title
|
|
||||||
>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<p>You have two options:</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Mention the bot in your tweet. The message of your tweet will be
|
|
||||||
broadcasted.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Write a direct message to the bot. The message will be broadcasted.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>Both options have the equal result.</p>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title>How to receive messages?</mat-panel-title>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<p>
|
|
||||||
Follow one of the twitter accounts in the twitter card. It will
|
|
||||||
broadcast all messages it receives by tweeting the content.
|
|
||||||
</p>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
<mat-expansion-panel>
|
|
||||||
<mat-expansion-panel-header>
|
|
||||||
<mat-panel-title>How to stop receiving messages?</mat-panel-title>
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<p>Just unfollow the twitter accounts that you previously followed.</p>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
</mat-accordion>
|
|
||||||
</div>
|
|
||||||
</mat-dialog-content>
|
|
|
@ -1,4 +0,0 @@
|
||||||
.container {
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-twitter-bot-info-dialog',
|
|
||||||
templateUrl: './twitter-bot-info-dialog.component.html',
|
|
||||||
styleUrls: ['./twitter-bot-info-dialog.component.scss'],
|
|
||||||
})
|
|
||||||
export class TwitterBotInfoDialogComponent implements OnInit {
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit(): void {}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<mat-spinner class="spinner"></mat-spinner>
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
.spinner {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { TwitterCallbackComponent } from './twitter-callback.component';
|
|
||||||
|
|
||||||
describe('TwitterCallbackComponent', () => {
|
|
||||||
let component: TwitterCallbackComponent;
|
|
||||||
let fixture: ComponentFixture<TwitterCallbackComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [TwitterCallbackComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(TwitterCallbackComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,47 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
import { TwitterService } from 'src/app/core/api';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-twitter-callback',
|
|
||||||
templateUrl: './twitter-callback.component.html',
|
|
||||||
styleUrls: ['./twitter-callback.component.scss'],
|
|
||||||
})
|
|
||||||
export class TwitterCallbackComponent implements OnInit {
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private twitterService: TwitterService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
if (
|
|
||||||
this.route.snapshot.queryParams.hood &&
|
|
||||||
this.route.snapshot.queryParams.oauth_token &&
|
|
||||||
this.route.snapshot.queryParams.oauth_verifier
|
|
||||||
) {
|
|
||||||
this.twitterService
|
|
||||||
.callbackTwitter(
|
|
||||||
this.route.snapshot.queryParams.oauth_token,
|
|
||||||
this.route.snapshot.queryParams.oauth_verifier,
|
|
||||||
this.route.snapshot.queryParams.hood
|
|
||||||
)
|
|
||||||
.subscribe(() => {
|
|
||||||
this.router.navigate([
|
|
||||||
'/dashboard/hoods',
|
|
||||||
this.route.snapshot.queryParams.hood,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
} else if (
|
|
||||||
this.route.snapshot.queryParams.hood &&
|
|
||||||
this.route.snapshot.queryParams.denied
|
|
||||||
) {
|
|
||||||
this.router.navigate([
|
|
||||||
'/dashboard/hoods',
|
|
||||||
this.route.snapshot.queryParams.hood,
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
this.router.navigate(['/404']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
name: 'twitterCorpses',
|
|
||||||
})
|
|
||||||
export class TwitterCorpsesPipe implements PipeTransform {
|
|
||||||
transform(twitters) {
|
|
||||||
return twitters.filter((x) => x.verified === 1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
<mat-dialog-content>
|
|
||||||
<h2>How to add an twitter bot to your hood</h2>
|
|
||||||
<h3>What is a twitter bot?</h3>
|
|
||||||
<p>
|
|
||||||
Twitter bots are twitter accounts operated by software. In our case we will
|
|
||||||
show you how to add a bot for users to subscribe to, so they can send
|
|
||||||
messages into your hood system by mentioning the bot or direct messaging it,
|
|
||||||
which get distributed to the other platforms. Also they can receive messages
|
|
||||||
from other platforms by reading the tweets of the bot.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Example: </strong> You as a hood admin added the bot
|
|
||||||
@kibicara-my-hood to your hood. John wants to send a message to all hood
|
|
||||||
subscribers. He then uses his twitter account to follow to the bot
|
|
||||||
@kibicara-my-hood and sends his message to the bot by sending a tweet. His
|
|
||||||
message will be distributed to the other platforms and Sandra who is
|
|
||||||
subscribed to your email hood bot gets John's message via email.
|
|
||||||
</p>
|
|
||||||
<h3>How to add a twitter bot to your hood?</h3>
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<a href="https://twitter.com" target="_blank">Create a twitter account</a>
|
|
||||||
for the twitter bot and log in. We recommend <strong>NOT</strong> to use
|
|
||||||
your own personal twitter account but to create a new seperate hood
|
|
||||||
account since you will give full access to the account to our software.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Click on the <strong>Add a new platform connection!</strong>-Button. This
|
|
||||||
will redirect you to the twitter page to authorize access to the twitter
|
|
||||||
account. Click the
|
|
||||||
<strong>Authorize app</strong>
|
|
||||||
Button. You will be redirected back here. Done!
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<img class="example-image" src="assets/auth-app-twitter.png" />
|
|
||||||
<h3>Can I stop relaying twitter messages?</h3>
|
|
||||||
<p>
|
|
||||||
Yes, if you want to stop relaying twitter messages from a specific twitter
|
|
||||||
bot, just use the switch to the bot to stop relaying.
|
|
||||||
</p>
|
|
||||||
</mat-dialog-content>
|
|
|
@ -1,9 +0,0 @@
|
||||||
.example-image {
|
|
||||||
margin-left: 10%;
|
|
||||||
margin-right: 10%;
|
|
||||||
@media screen and (max-width: 600px) {
|
|
||||||
width: 100%;
|
|
||||||
margin-left: 0%;
|
|
||||||
margin-right: 0%;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-twitter-info-dialog',
|
|
||||||
templateUrl: './twitter-info-dialog.component.html',
|
|
||||||
styleUrls: ['./twitter-info-dialog.component.scss'],
|
|
||||||
})
|
|
||||||
export class TwitterInfoDialogComponent implements OnInit {
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit(): void {}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
<mat-card appearance="outlined">
|
|
||||||
<mat-card-header>
|
|
||||||
<div mat-card-avatar class="twitter"></div>
|
|
||||||
<mat-card-title class="platform-title">
|
|
||||||
Twitter
|
|
||||||
<button mat-icon-button aria-label="How to use">
|
|
||||||
<mat-icon
|
|
||||||
matTooltip="How to add an twitter bot to your hood"
|
|
||||||
class="info-button"
|
|
||||||
(click)="onInfoClick()"
|
|
||||||
>info</mat-icon
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</mat-card-title>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content>
|
|
||||||
<mat-list *ngIf="twitters$ | loading | async as twitters">
|
|
||||||
<ng-template [ngIf]="twitters.value">
|
|
||||||
<mat-list-item *ngIf="(twitters.value | twitterCorpses).length === 0">
|
|
||||||
<button class="add-button" mat-button (click)="onCreate()">
|
|
||||||
<div class="in-add-button">
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
<span> Add a platform connection!</span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</mat-list-item>
|
|
||||||
<mat-list-item *ngFor="let twitter of twitters.value | twitterCorpses">
|
|
||||||
<div class="entry">
|
|
||||||
@{{ twitter.username }}
|
|
||||||
<mat-slide-toggle
|
|
||||||
[checked]="twitter.enabled === 1"
|
|
||||||
(change)="onChange(twitter)"
|
|
||||||
></mat-slide-toggle>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
[matMenuTriggerFor]="menu"
|
|
||||||
aria-label="Example icon-button with a menu"
|
|
||||||
>
|
|
||||||
<mat-icon>more_vert</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<mat-menu #menu="matMenu">
|
|
||||||
<button mat-menu-item (click)="onDelete(twitter.id)">
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span>Delete</span>
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item (click)="onCreate()">
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
<span>Add another</span>
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
|
||||||
</mat-list-item>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template [ngIf]="twitters.error"
|
|
||||||
><mat-icon class="warning">warning</mat-icon></ng-template
|
|
||||||
>
|
|
||||||
<ng-template [ngIf]="twitters.loading">
|
|
||||||
<mat-spinner [diameter]="45" class="spinner"></mat-spinner>
|
|
||||||
</ng-template>
|
|
||||||
</mat-list>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
|
@ -1,22 +0,0 @@
|
||||||
.entry {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 4fr 40px 20px;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-title {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 40px;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-heading {
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter {
|
|
||||||
background-image: url("../../../../assets/twitter.png");
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { TwitterSettingsComponent } from './twitter-settings.component';
|
|
||||||
|
|
||||||
describe('TwitterSettingsComponent', () => {
|
|
||||||
let component: TwitterSettingsComponent;
|
|
||||||
let fixture: ComponentFixture<TwitterSettingsComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [TwitterSettingsComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(TwitterSettingsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,77 +0,0 @@
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { TwitterService } from 'src/app/core/api';
|
|
||||||
import { TwitterInfoDialogComponent } from './twitter-info-dialog/twitter-info-dialog.component';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-twitter-settings',
|
|
||||||
templateUrl: './twitter-settings.component.html',
|
|
||||||
styleUrls: ['./twitter-settings.component.scss'],
|
|
||||||
})
|
|
||||||
export class TwitterSettingsComponent implements OnInit {
|
|
||||||
@Input() hoodId;
|
|
||||||
twitters$: Observable<Array<any>>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private twitterService: TwitterService,
|
|
||||||
public dialog: MatDialog,
|
|
||||||
private snackBar: MatSnackBar
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
private reload() {
|
|
||||||
this.twitters$ = this.twitterService.getTwitters(this.hoodId);
|
|
||||||
}
|
|
||||||
|
|
||||||
onInfoClick() {
|
|
||||||
this.dialog.open(TwitterInfoDialogComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete(twitterId) {
|
|
||||||
this.twitterService.deleteTwitter(twitterId, this.hoodId).subscribe(() => {
|
|
||||||
this.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onCreate() {
|
|
||||||
this.twitterService.createTwitter(this.hoodId).subscribe((twitter) => {
|
|
||||||
if (twitter && twitter.access_token) {
|
|
||||||
const redirectUrl =
|
|
||||||
'https://api.twitter.com/oauth/authorize?oauth_token=' +
|
|
||||||
twitter.access_token;
|
|
||||||
window.location.href = redirectUrl;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(twitter) {
|
|
||||||
if (twitter.enabled === 0) {
|
|
||||||
this.twitterService.startTwitter(twitter.id, this.hoodId).subscribe(
|
|
||||||
() => {},
|
|
||||||
(error) => {
|
|
||||||
this.snackBar.open('Could not start. Check your settings.', 'Close', {
|
|
||||||
duration: 2000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else if (twitter.enabled === 1) {
|
|
||||||
this.twitterService.stopTwitter(twitter.id, this.hoodId).subscribe(
|
|
||||||
() => {},
|
|
||||||
(error) => {
|
|
||||||
this.snackBar.open('Could not stop. Check your settings.', 'Close', {
|
|
||||||
duration: 2000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// TODO yeah i know this is bad, implement disabling/enabling
|
|
||||||
setTimeout(() => {
|
|
||||||
this.reload();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -112,11 +112,6 @@
|
||||||
use. If you are a normal user:
|
use. If you are a normal user:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
|
||||||
Twitter: We save the id of the last received message (mentions and
|
|
||||||
direct messages). This can be a message of yours if you sent the
|
|
||||||
latest message.
|
|
||||||
</li>
|
|
||||||
<li>Telegram: We save your telegram username.</li>
|
<li>Telegram: We save your telegram username.</li>
|
||||||
<li>E-Mail: We save your e-mail address.</li>
|
<li>E-Mail: We save your e-mail address.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -130,12 +125,6 @@
|
||||||
<p>For hood admins:</p>
|
<p>For hood admins:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>We save your e-mail address and your password.</li>
|
<li>We save your e-mail address and your password.</li>
|
||||||
<li>
|
|
||||||
Twitter: We save oauth tokens provided by twitter that give us access
|
|
||||||
to the twitter account and the username of the twitter account. We
|
|
||||||
disadvice the use of your private twitter account for acting as
|
|
||||||
Kibicara platform bot. Please create a new twitter account.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
Telegram: We save the telegram API token to the provided telegram bot
|
Telegram: We save the telegram API token to the provided telegram bot
|
||||||
and a welcome message. Also we retrieve the name of the telegram bot.
|
and a welcome message. Also we retrieve the name of the telegram bot.
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<div class="big-paragraph-font">
|
<div class="big-paragraph-font">
|
||||||
<h2 class="big-h2-font">Inclusive and easy</h2>
|
<h2 class="big-h2-font">Inclusive and easy</h2>
|
||||||
<p>
|
<p>
|
||||||
Messages sent with Kibicara reach people via Telegram, Twitter and even
|
Messages sent with Kibicara reach people via Telegram, Mastodon and even
|
||||||
E-Mail - perfect for announcing the next neighborhood meetings, creating
|
E-Mail - perfect for announcing the next neighborhood meetings, creating
|
||||||
news tickers or even providing disaster warnings.
|
news tickers or even providing disaster warnings.
|
||||||
</p>
|
</p>
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
community-administrated instances of Kibicara, being able to customize
|
community-administrated instances of Kibicara, being able to customize
|
||||||
different platform accounts and filters. You subscribe to a Kibicara hood
|
different platform accounts and filters. You subscribe to a Kibicara hood
|
||||||
through your service of choice. This can either be E-Mail, Telegram or
|
through your service of choice. This can either be E-Mail, Telegram or
|
||||||
Twitter.
|
Mastodon.
|
||||||
</p>
|
</p>
|
||||||
<a mat-raised-button [routerLink]="['/hoods']">Discover hoods!</a>
|
<a mat-raised-button [routerLink]="['/hoods']">Discover hoods!</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#
|
#
|
||||||
# client-side git-hook - checks commit message style
|
# client-side git-hook - checks commit message style
|
||||||
|
|
||||||
pattern='\[(core|frontend|twitter|telegram|email|xmpp|mastodon|tests|doc|misc)\] [[:upper:]].*[^.]'
|
pattern='\[(core|frontend|telegram|email|xmpp|mastodon|tests|doc|misc)\] [[:upper:]].*[^.]'
|
||||||
head -n 1 "$1" | egrep -x "$pattern" > /dev/null
|
head -n 1 "$1" | egrep -x "$pattern" > /dev/null
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "commit message doesn't match \"$pattern\"" >&2
|
echo "commit message doesn't match \"$pattern\"" >&2
|
||||||
|
|
Loading…
Reference in a new issue