Skip to content

Commit

Permalink
Merge d07e9c9 into 99c2a7b
Browse files Browse the repository at this point in the history
  • Loading branch information
MrOrz committed Oct 12, 2023
2 parents 99c2a7b + d07e9c9 commit 770d70a
Show file tree
Hide file tree
Showing 14 changed files with 528 additions and 527 deletions.
397 changes: 73 additions & 324 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"@storybook/addon-links": "^6.2.9",
"@storybook/addon-svelte-csf": "^2.0.11",
"@storybook/svelte": "^6.2.9",
"@total-typescript/ts-reset": "^0.5.1",
"@types/jest": "^24.9.1",
"@types/koa-router": "^7.4.4",
"@types/string-similarity": "^4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/database/models/userArticleLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class UserArticleLink extends Base {
*
* @param {string} userId
* @param {string} articleId
* @param {object} data
* @param {object} [data]
* @returns {Promise<UserArticleLink>}
*/
static async createOrUpdateByUserIdAndArticleId(userId, articleId, data) {
Expand Down
62 changes: 38 additions & 24 deletions src/graphql/cofacts-api.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Query {
"""
GetUser(id: String, slug: String): User
GetCategory(id: String): Category
GetYdoc(id: String!): Ydoc
ListArticles(
filter: ListArticleFilter
orderBy: [ListArticleOrderBy]
Expand Down Expand Up @@ -176,13 +177,13 @@ type Query {
type Article implements Node {
id: ID!
text: String
createdAt: String
createdAt: String!
updatedAt: String
status: ReplyRequestStatusEnum!
references: [ArticleReference]

"""Number of normal article replies"""
replyCount: Int
replyCount: Int!

"""
Connections between this article and replies. Sorted by the logic described in https://github.com/cofacts/rumors-line-bot/issues/78.
Expand All @@ -207,7 +208,7 @@ type Article implements Node {

"""Only list the articleReplies created by the currently logged in user"""
selfOnly: Boolean
): [ArticleReply]
): [ArticleReply!]!

"""
Automated reply from AI before human fact checkers compose an fact check
Expand All @@ -224,10 +225,10 @@ type Article implements Node {

"""Returns only article categories with the specified statuses"""
statuses: [ArticleCategoryStatusEnum!] = [NORMAL]
): [ArticleCategory]
): [ArticleCategory!]!

"""Number of normal article categories"""
categoryCount: Int
categoryCount: Int!
replyRequests(
"""Returns only article replies with the specified statuses"""
statuses: [ReplyRequestStatusEnum!] = [NORMAL]
Expand Down Expand Up @@ -258,7 +259,7 @@ type Article implements Node {
Specify a cursor, returns results before this cursor. cannot be used with "after".
"""
before: String
): ArticleConnection
): ArticleConnection!

"""Hyperlinks in article text"""
hyperlinks: [Hyperlink]
Expand Down Expand Up @@ -293,8 +294,8 @@ enum ReplyRequestStatusEnum {
}

type ArticleReference {
createdAt: String
type: ArticleReferenceTypeEnum
createdAt: String!
type: ArticleReferenceTypeEnum!
permalink: String
}

Expand All @@ -311,33 +312,33 @@ enum ArticleReferenceTypeEnum {

"""The linkage between an Article and a Reply"""
type ArticleReply {
replyId: String
replyId: String!
reply: Reply

"""Cached reply type value stored in ArticleReply"""
replyType: ReplyTypeEnum
articleId: String
articleId: String!
article: Article

"""The user who conencted this reply and this article."""
user: User
userId: String!
appId: String!
canUpdateStatus: Boolean
feedbackCount: Int
positiveFeedbackCount: Int
negativeFeedbackCount: Int
canUpdateStatus: Boolean!
feedbackCount: Int!
positiveFeedbackCount: Int!
negativeFeedbackCount: Int!
feedbacks(
"""Returns only aricle reply feedbacks with the specified statuses"""
statuses: [ArticleReplyFeedbackStatusEnum!] = [NORMAL]
): [ArticleReplyFeedback]
): [ArticleReplyFeedback!]!

"""
The feedback of current user. null when not logged in or not voted yet.
"""
ownVote: FeedbackVote
status: ArticleReplyStatusEnum
createdAt: String
status: ArticleReplyStatusEnum!
createdAt: String!
updatedAt: String
}

Expand All @@ -346,17 +347,17 @@ type Reply implements Node {

"""The user submitted this reply version"""
user: User
createdAt: String
createdAt: String!
text: String
type: ReplyTypeEnum
type: ReplyTypeEnum!
reference: String
articleReplies(
"""Deprecated. Please use statuses instead."""
status: ArticleReplyStatusEnum

"""Returns only article replies with the specified statuses"""
statuses: [ArticleReplyStatusEnum!] = [NORMAL]
): [ArticleReply]
): [ArticleReply!]!

"""
Hyperlinks in reply text or reference. May be empty array if no URLs are included. `null` when hyperlinks are still fetching.
Expand All @@ -379,7 +380,7 @@ type Reply implements Node {
Specify a cursor, returns results before this cursor. cannot be used with "after".
"""
before: String
): ReplyConnection
): ReplyConnection!
}

type User implements Node {
Expand Down Expand Up @@ -979,6 +980,21 @@ type Cooccurrence implements Node {
updatedAt: String!
}

type Ydoc {
"""Binary that stores as base64 encoded string"""
data: String

"""Ydoc snapshots which are used to restore to specific version"""
versions: [YdocVersion]
}

type YdocVersion {
createdAt: String

"""Binary that stores as base64 encoded string"""
snapshot: String
}

input ListArticleFilter {
"""Show only articles created by a specific app."""
appId: String
Expand Down Expand Up @@ -1557,9 +1573,7 @@ type Mutation {
articleType: ArticleTypeEnum!
reference: ArticleReferenceInput!

"""
The reason why the user want to submit this article. Mandatory for 1st sender
"""
"""The reason why the user want to submit this article"""
reason: String
): MutationResult

Expand Down
3 changes: 3 additions & 0 deletions src/types/chatbotState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ export type Context = {
/** User selected article in DB */
selectedArticleId?: string;
selectedArticleText?: string;

/** FIXME: Probably not required now */
selectedReplyId?: string;
};

export type ChatbotStateHandlerParams = {
Expand Down
1 change: 1 addition & 0 deletions src/types/reset.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@total-typescript/ts-reset';
1 change: 0 additions & 1 deletion src/webhook/handlers/__tests__/askingArticleSource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ it('returns instructions if user did not forward the whole message', async () =>
"type": "span",
},
],
"text": "Instructions",
"type": "text",
"wrap": true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import {
} from './utils';

import { TUTORIAL_STEPS } from './tutorial';
import { ChatbotStateHandler } from 'src/types/chatbotState';

export default async function askingArticleSource(params) {
let { data, state, event, userId, replies } = params;
const askingArticleSource: ChatbotStateHandler = async (params) => {
const { data, state, event, userId } = params;
let { replies } = params;

const visitor = ga(userId, state, data.searchedText);

Expand All @@ -25,7 +27,7 @@ export default async function askingArticleSource(params) {
case POSTBACK_NO:
replies = [
createTextMessage({
text: t`Instructions`,
altText: t`Instructions`,
contents: [
{
type: 'span',
Expand Down Expand Up @@ -171,4 +173,6 @@ export default async function askingArticleSource(params) {
visitor.send();

return { data, event, userId, replies };
}
};

export default askingArticleSource;
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { t } from 'ttag';
import { Message } from '@line/bot-sdk';

import { ChatbotStateHandler } from 'src/types/chatbotState';
import ga from 'src/lib/ga';
import gql from 'src/lib/gql';
import { getArticleURL } from 'src/lib/sharedUtils';
Expand All @@ -15,9 +18,21 @@ import {
} from './utils';
import UserSettings from 'src/database/models/userSettings';
import UserArticleLink from 'src/database/models/userArticleLink';
import {
ArticleTypeEnum,
SubmitMediaArticleUnderConsentMutation,
SubmitMediaArticleUnderConsentMutationVariables,
SubmitTextArticleUnderConsentMutation,
SubmitTextArticleUnderConsentMutationVariables,
} from 'typegen/graphql';

function uppercase<T extends string>(s: T) {
return s.toUpperCase() as Uppercase<T>;
}

export default async function askingArticleSubmissionConsent(params) {
let { data, state, event, userId, replies } = params;
const askingArticleSubmissionConsent: ChatbotStateHandler = async (params) => {
const { data, event, userId } = params;
let { state, replies } = params;

const visitor = ga(userId, state, data.searchedText);

Expand All @@ -41,22 +56,43 @@ export default async function askingArticleSubmissionConsent(params) {
let article;
if (isTextArticle) {
const result = await gql`
mutation ($text: String!) {
mutation SubmitTextArticleUnderConsent($text: String!) {
CreateArticle(text: $text, reference: { type: LINE }) {
id
}
}
`({ text: data.searchedText }, { userId });
`<
SubmitTextArticleUnderConsentMutation,
SubmitTextArticleUnderConsentMutationVariables
>({ text: data.searchedText ?? '' }, { userId });
article = result.data.CreateArticle;
} else {
/* istanbul ignore if */
if (!data.messageId) {
// Should not be here
throw new Error('No message ID found, cannot submit message.');
}

const articleType: ArticleTypeEnum = (() => {
switch (data.messageType) {
case 'image':
case 'audio':
case 'video':
return uppercase(data.messageType);
default:
throw new Error(
`[askingArticleSubmissionConsent] unsupported message type ${data.messageType}`
);
}
})();

const proxyUrl = getLineContentProxyURL(data.messageId);

const result = await gql`
mutation ($mediaUrl: String!, $articleType: ArticleTypeEnum!) {
mutation SubmitMediaArticleUnderConsent(
$mediaUrl: String!
$articleType: ArticleTypeEnum!
) {
CreateMediaArticle(
mediaUrl: $mediaUrl
articleType: $articleType
Expand All @@ -65,13 +101,20 @@ export default async function askingArticleSubmissionConsent(params) {
id
}
}
`(
{ mediaUrl: proxyUrl, articleType: data.messageType.toUpperCase() },
{ userId }
);
`<
SubmitMediaArticleUnderConsentMutation,
SubmitMediaArticleUnderConsentMutationVariables
>({ mediaUrl: proxyUrl, articleType }, { userId });
article = result.data.CreateMediaArticle;
}

/* istanbul ignore if */
if (!article?.id) {
throw new Error(
'[askingArticleSubmissionConsent] article is not created successfully'
);
}

await UserArticleLink.createOrUpdateByUserIdAndArticleId(
userId,
article.id
Expand All @@ -86,7 +129,7 @@ export default async function askingArticleSubmissionConsent(params) {
userId
);

let maybeAIReplies = [
let maybeAIReplies: Message[] = [
createTextMessage({
text: t`In the meantime, you can:`,
}),
Expand Down Expand Up @@ -150,7 +193,7 @@ export default async function askingArticleSubmissionConsent(params) {
!allowNewReplyUpdate &&
createNotificationSettingsBubble(),
createArticleShareBubble(articleUrl),
].filter((m) => m),
].filter(Boolean),
},
},
];
Expand All @@ -160,4 +203,6 @@ export default async function askingArticleSubmissionConsent(params) {

visitor.send();
return { data, event, userId, replies };
}
};

export default askingArticleSubmissionConsent;

0 comments on commit 770d70a

Please sign in to comment.