diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 5d7c638..c91ac78 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -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` -#### 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 = '' -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 Nothing to do, because telegram has a nice API. diff --git a/backend/src/kibicara/platforms/twitter/__init__.py b/backend/src/kibicara/platforms/twitter/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/src/kibicara/platforms/twitter/bot.py b/backend/src/kibicara/platforms/twitter/bot.py deleted file mode 100644 index dc1db68..0000000 --- a/backend/src/kibicara/platforms/twitter/bot.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (C) 2020 by Cathy Hu -# Copyright (C) 2020 by Martin Rey -# -# 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) diff --git a/backend/src/kibicara/platforms/twitter/model.py b/backend/src/kibicara/platforms/twitter/model.py deleted file mode 100644 index 73a76ea..0000000 --- a/backend/src/kibicara/platforms/twitter/model.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2020 by Cathy Hu -# Copyright (C) 2020 by Martin Rey -# -# 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" diff --git a/backend/src/kibicara/platforms/twitter/webapi.py b/backend/src/kibicara/platforms/twitter/webapi.py deleted file mode 100644 index e00c467..0000000 --- a/backend/src/kibicara/platforms/twitter/webapi.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright (C) 2020 by Cathy Hu -# Copyright (C) 2020 by Martin Rey -# -# 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) diff --git a/backend/src/kibicara/webapi/__init__.py b/backend/src/kibicara/webapi/__init__.py index af769c3..20fc8bd 100644 --- a/backend/src/kibicara/webapi/__init__.py +++ b/backend/src/kibicara/webapi/__init__.py @@ -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.test.webapi import router as test_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.hoods import router as hoods_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( telegram_router, prefix="/{hood_id}/telegram", tags=["telegram"] ) -hoods_router.include_router( - twitter_router, prefix="/{hood_id}/twitter", tags=["twitter"] -) hoods_router.include_router( 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"]) router.include_router(hoods_router, prefix="/hoods") diff --git a/frontend/src/app/core/api/api.module.ts b/frontend/src/app/core/api/api.module.ts index b3a7ddb..3760153 100644 --- a/frontend/src/app/core/api/api.module.ts +++ b/frontend/src/app/core/api/api.module.ts @@ -10,7 +10,6 @@ import { MastodonService } from './api/mastodon.service'; import { TelegramService } from './api/telegram.service'; import { TestService } from './api/test.service'; import { TriggersService } from './api/triggers.service'; -import { TwitterService } from './api/twitter.service'; @NgModule({ imports: [], diff --git a/frontend/src/app/core/api/api/api.ts b/frontend/src/app/core/api/api/api.ts index 69e9b19..832c9d7 100644 --- a/frontend/src/app/core/api/api/api.ts +++ b/frontend/src/app/core/api/api/api.ts @@ -14,6 +14,4 @@ export * from './test.service'; import { TestService } from './test.service'; export * from './triggers.service'; import { TriggersService } from './triggers.service'; -export * from './twitter.service'; -import { TwitterService } from './twitter.service'; -export const APIS = [AdminService, BadwordsService, EmailService, HoodsService, MastodonService, TelegramService, TestService, TriggersService, TwitterService]; +export const APIS = [AdminService, BadwordsService, EmailService, HoodsService, MastodonService, TelegramService, TestService, TriggersService]; diff --git a/frontend/src/app/core/api/api/twitter.service.ts b/frontend/src/app/core/api/api/twitter.service.ts deleted file mode 100644 index b686fe9..0000000 --- a/frontend/src/app/core/api/api/twitter.service.ts +++ /dev/null @@ -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; - public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public callbackTwitter(oauthToken: string, oauthVerifier: string, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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, - oauthToken, 'oauth_token'); - } - if (oauthVerifier !== undefined && oauthVerifier !== null) { - queryParameters = this.addToHttpParams(queryParameters, - oauthVerifier, 'oauth_verifier'); - } - if (hoodId !== undefined && hoodId !== null) { - queryParameters = this.addToHttpParams(queryParameters, - 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(`${this.configuration.basePath}/api/twitter/callback`, - { - params: queryParameters, - responseType: 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; - public createTwitter(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public createTwitter(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public createTwitter(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/`, - null, - { - responseType: 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; - public deleteTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public deleteTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public deleteTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}`, - { - responseType: 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; - public getTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}`, - { - responseType: 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; - public getTwitters(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwitters(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwitters(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/`, - { - responseType: 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; - public getTwittersPublic(hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwittersPublic(hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public getTwittersPublic(hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/public`, - { - responseType: 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; - public startTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public startTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public startTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/start`, - null, - { - responseType: 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; - public statusTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public statusTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public statusTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/status`, - { - responseType: 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; - public stopTwitter(twitterId: number, hoodId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public stopTwitter(twitterId: number, hoodId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json'}): Observable>; - public stopTwitter(twitterId: number, hoodId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json'}): Observable { - 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(`${this.configuration.basePath}/api/hoods/${encodeURIComponent(String(hoodId))}/twitter/${encodeURIComponent(String(twitterId))}/stop`, - null, - { - responseType: responseType, - withCredentials: this.configuration.withCredentials, - headers: headers, - observe: observe, - reportProgress: reportProgress - } - ); - } - -} diff --git a/frontend/src/app/dashboard/board/hoodpage/hoodpage.component.html b/frontend/src/app/dashboard/board/hoodpage/hoodpage.component.html index 5acf7d2..dd41c53 100644 --- a/frontend/src/app/dashboard/board/hoodpage/hoodpage.component.html +++ b/frontend/src/app/dashboard/board/hoodpage/hoodpage.component.html @@ -49,8 +49,8 @@

Share the hood page: Just send the link to your hood page to your community. We also recommend to link it in your platform - account description (e.g. Twitter description) to give the users - context and more information. + account description (e.g. Mastodon account description) to give the + users context and more information.

diff --git a/frontend/src/app/dashboard/board/platforms/platforms.component.html b/frontend/src/app/dashboard/board/platforms/platforms.component.html index d4c4987..c3d050d 100644 --- a/frontend/src/app/dashboard/board/platforms/platforms.component.html +++ b/frontend/src/app/dashboard/board/platforms/platforms.component.html @@ -37,7 +37,6 @@
-
diff --git a/frontend/src/app/dashboard/dashboard-routing.module.ts b/frontend/src/app/dashboard/dashboard-routing.module.ts index 927e068..483a1d7 100644 --- a/frontend/src/app/dashboard/dashboard-routing.module.ts +++ b/frontend/src/app/dashboard/dashboard-routing.module.ts @@ -4,7 +4,6 @@ import { DashboardComponent } from './dashboard.component'; import { HoodsComponent } from './hoods/hoods.component'; import { AuthGuard } from '../core/auth/auth.guard'; import { BoardComponent } from './board/board.component'; -import { TwitterCallbackComponent } from '../platforms/twitter/twitter-callback/twitter-callback.component'; import { AccountSettingsComponent } from './account-settings/account-settings.component'; const routes: Routes = [ @@ -15,8 +14,6 @@ const routes: Routes = [ { path: '', component: HoodsComponent }, { path: 'hoods/:id', component: BoardComponent }, { path: 'settings', component: AccountSettingsComponent }, - // Platform-specific Routes - { path: 'twitter-callback', component: TwitterCallbackComponent }, ], canActivate: [AuthGuard], }, diff --git a/frontend/src/app/platforms/platforms-info-page/platforms-info-page.component.html b/frontend/src/app/platforms/platforms-info-page/platforms-info-page.component.html index 3d3b646..3c4f29a 100644 --- a/frontend/src/app/platforms/platforms-info-page/platforms-info-page.component.html +++ b/frontend/src/app/platforms/platforms-info-page/platforms-info-page.component.html @@ -1,6 +1,5 @@

Platforms - choose one, get all hood messages

- diff --git a/frontend/src/app/platforms/platforms.module.ts b/frontend/src/app/platforms/platforms.module.ts index b9bb530..32802fe 100644 --- a/frontend/src/app/platforms/platforms.module.ts +++ b/frontend/src/app/platforms/platforms.module.ts @@ -2,22 +2,16 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TelegramSettingsComponent } from './telegram/telegram-settings/telegram-settings.component'; 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 { EmailDialogComponent } from './email/email-settings/email-dialog/email-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 { 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 { EmailBotCardComponent } from './email/email-bot-card/email-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 { 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 { EmailUnsubscribeComponent } from './email/email-unsubscribe/email-unsubscribe.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({ declarations: [ TelegramSettingsComponent, - TwitterSettingsComponent, EmailSettingsComponent, EmailDialogComponent, EmailInfoDialogComponent, TelegramInfoDialogComponent, TelegramDialogComponent, - TwitterInfoDialogComponent, - TwitterCallbackComponent, - TwitterCorpsesPipe, PlatformsInfoPageComponent, EmailBotCardComponent, TelegramBotCardComponent, - TwitterBotCardComponent, EmailBotInfoDialogComponent, TelegramBotInfoDialogComponent, - TwitterBotInfoDialogComponent, EmailConfirmationComponent, EmailUnsubscribeComponent, MastodonBotCardComponent, @@ -55,7 +43,6 @@ import { MastodonBotInfoDialogComponent } from './mastodon/mastodon-bot-card/mas exports: [ TelegramSettingsComponent, MastodonSettingsComponent, - TwitterSettingsComponent, EmailSettingsComponent, PlatformsInfoPageComponent, ], diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.html b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.html deleted file mode 100644 index a668aad..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.html +++ /dev/null @@ -1,46 +0,0 @@ -
- - - - - - Twitter - - - - - - - - @{{ twitter.username }} - - - - - - - - - Unfortunately your hood admin has not configured Twitter as platform - yet. - - - - warning - - - -
diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.scss b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.scss deleted file mode 100644 index 71cb1d3..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.scss +++ /dev/null @@ -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; -} diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.spec.ts b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.spec.ts deleted file mode 100644 index 2312ffc..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.spec.ts +++ /dev/null @@ -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; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [TwitterBotCardComponent], - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(TwitterBotCardComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.ts b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.ts deleted file mode 100644 index ffd2673..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-card.component.ts +++ /dev/null @@ -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); - } -} diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.html b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.html deleted file mode 100644 index dd7d2d8..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.html +++ /dev/null @@ -1,51 +0,0 @@ - -
-

How to communicate with the hood via Twitter?

- - - - How to subscribe to the hood via Twitter? - -

- Click on the twitter bot name that is shown in the twitter card. Just - follow the twitter account that the link leads to. -

-
- - - How to send a broadcast message to the hood? - -

You have two options:

-
    -
  • - Mention the bot in your tweet. The message of your tweet will be - broadcasted. -
  • -
  • - Write a direct message to the bot. The message will be broadcasted. -
  • -
-

Both options have the equal result.

-
- - - How to receive messages? - -

- Follow one of the twitter accounts in the twitter card. It will - broadcast all messages it receives by tweeting the content. -

-
- - - How to stop receiving messages? - -

Just unfollow the twitter accounts that you previously followed.

-
-
-
-
diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.scss b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.scss deleted file mode 100644 index 79cc5e7..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.container { - margin-top: 10px; - margin-bottom: 10px; -} diff --git a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.ts b/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.ts deleted file mode 100644 index f7ac2e0..0000000 --- a/frontend/src/app/platforms/twitter/twitter-bot-card/twitter-bot-info-dialog/twitter-bot-info-dialog.component.ts +++ /dev/null @@ -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 {} -} diff --git a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.html b/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.html deleted file mode 100644 index 113e652..0000000 --- a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.scss b/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.scss deleted file mode 100644 index 86c0c51..0000000 --- a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.spinner { - display: block; - margin: auto; -} diff --git a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.spec.ts b/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.spec.ts deleted file mode 100644 index 2a6abf0..0000000 --- a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.spec.ts +++ /dev/null @@ -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; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [TwitterCallbackComponent], - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(TwitterCallbackComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.ts b/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.ts deleted file mode 100644 index ef0fde3..0000000 --- a/frontend/src/app/platforms/twitter/twitter-callback/twitter-callback.component.ts +++ /dev/null @@ -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']); - } - } -} diff --git a/frontend/src/app/platforms/twitter/twitter-corpses-pipe/twitter-corpses.pipe.ts b/frontend/src/app/platforms/twitter/twitter-corpses-pipe/twitter-corpses.pipe.ts deleted file mode 100644 index b7b8791..0000000 --- a/frontend/src/app/platforms/twitter/twitter-corpses-pipe/twitter-corpses.pipe.ts +++ /dev/null @@ -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); - } -} diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.html b/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.html deleted file mode 100644 index 2c0180e..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.html +++ /dev/null @@ -1,41 +0,0 @@ - -

How to add an twitter bot to your hood

-

What is a twitter bot?

-

- 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. -

-

- Example: 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. -

-

How to add a twitter bot to your hood?

-
    -
  1. - Create a twitter account - for the twitter bot and log in. We recommend NOT 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. -
  2. -
  3. - Click on the Add a new platform connection!-Button. This - will redirect you to the twitter page to authorize access to the twitter - account. Click the - Authorize app - Button. You will be redirected back here. Done! -
  4. -
- -

Can I stop relaying twitter messages?

-

- Yes, if you want to stop relaying twitter messages from a specific twitter - bot, just use the switch to the bot to stop relaying. -

-
diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.scss b/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.scss deleted file mode 100644 index 6002fed..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.scss +++ /dev/null @@ -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%; - } -} diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.ts b/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.ts deleted file mode 100644 index 121a43a..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-info-dialog/twitter-info-dialog.component.ts +++ /dev/null @@ -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 {} -} diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.html b/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.html deleted file mode 100644 index c0519b6..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Twitter - - - - - - - - - - - -
- @{{ twitter.username }} - - -
- - - - - -
-
- warning - - - -
-
-
diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.scss b/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.scss deleted file mode 100644 index 4a48207..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.scss +++ /dev/null @@ -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; -} diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.spec.ts b/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.spec.ts deleted file mode 100644 index 57b8462..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.spec.ts +++ /dev/null @@ -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; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [TwitterSettingsComponent], - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(TwitterSettingsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.ts b/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.ts deleted file mode 100644 index 76eedf7..0000000 --- a/frontend/src/app/platforms/twitter/twitter-settings/twitter-settings.component.ts +++ /dev/null @@ -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>; - - 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); - } -} diff --git a/frontend/src/app/public-pages/homepage/faq/faq.component.html b/frontend/src/app/public-pages/homepage/faq/faq.component.html index 2ce4474..0214bd5 100644 --- a/frontend/src/app/public-pages/homepage/faq/faq.component.html +++ b/frontend/src/app/public-pages/homepage/faq/faq.component.html @@ -112,11 +112,6 @@ use. If you are a normal user:

    -
  • - 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. -
  • Telegram: We save your telegram username.
  • E-Mail: We save your e-mail address.
@@ -130,12 +125,6 @@

For hood admins:

  • We save your e-mail address and your password.
  • -
  • - 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. -
  • 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. diff --git a/frontend/src/app/public-pages/homepage/homepage.component.html b/frontend/src/app/public-pages/homepage/homepage.component.html index 30d56e3..62c6d08 100644 --- a/frontend/src/app/public-pages/homepage/homepage.component.html +++ b/frontend/src/app/public-pages/homepage/homepage.component.html @@ -31,7 +31,7 @@

    Inclusive and easy

    - 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 news tickers or even providing disaster warnings.

    @@ -47,7 +47,7 @@ community-administrated instances of Kibicara, being able to customize different platform accounts and filters. You subscribe to a Kibicara hood through your service of choice. This can either be E-Mail, Telegram or - Twitter. + Mastodon.

    Discover hoods!
    diff --git a/git-hooks/commit-msg b/git-hooks/commit-msg index 163ef4d..48daf2a 100755 --- a/git-hooks/commit-msg +++ b/git-hooks/commit-msg @@ -6,7 +6,7 @@ # # 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 if [ $? -ne 0 ]; then echo "commit message doesn't match \"$pattern\"" >&2