Passed
Push — dev ( b8ced8...f7ea32 )
by Dispositif
07:14
created

TalkBotConfig::botContribs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 * This file is part of dispositif/wikibot application
4
 * 2019 : Philippe M. <[email protected]>
5
 * For the full copyright and MIT license information, please view the LICENSE file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Application;
11
12
use App\Domain\Utils\TextUtil;
13
use App\Infrastructure\ServiceFactory;
14
use Exception;
15
use Mediawiki\Api\UsageException;
16
use Mediawiki\DataModel\EditInfo;
17
18
/**
19
 * Freaky customization of WikiBotConfig class
20
 * Class TalkBotConfig.
21
 */
22
class TalkBotConfig extends WikiBotConfig
23
{
24
    const BOT_TALK_SUMMARY = 'Réponse artificielle';
25
26
    const BOT_TALK_FILE = __DIR__.'/resources/phrases_zizibot.txt';
27
28
    /**
29
     * Add a freaky response in the bottom of the talk page.
30
     *
31
     * @param string|null $pageTitle
32
     *
33
     * @return bool
34
     * @throws UsageException
35
     */
36
    public function botTalk(?string $pageTitle = null): bool
37
    {
38
        // ugly dependency
39
        $wiki = ServiceFactory::wikiApi();
40
        if (!$pageTitle) {
41
            $pageTitle = 'Discussion utilisateur:'.getenv('BOT_NAME');
42
        }
43
        $page = new WikiPageAction($wiki, $pageTitle);
44
        $last = $page->page->getRevisions()->getLatest();
45
46
        // No response if the last edition from bot or bot owner
47
        if (!$last->getUser()
48
            || in_array($last->getUser(), [getenv('BOT_NAME'), getenv('BOT_OWNER')])
49
            || 'Flow talk page manager' === $last->getUser()
50
        ) {
51
            // compare with timestamp
52
            return false;
53
        }
54
55
        $identation = $this->predictTalkIndentation($page->getText(), $last->getUser()); // ':::'
1 ignored issue
show
Bug introduced by
It seems like $page->getText() can also be of type null; however, parameter $text of App\Application\TalkBotC...redictTalkIndentation() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        $identation = $this->predictTalkIndentation(/** @scrutinizer ignore-type */ $page->getText(), $last->getUser()); // ':::'
Loading history...
56
        $addText = $this->generateTalkText($last->getUser(), $identation);
57
58
        echo "Prepare to talk on $pageTitle / Sleep 3 min...\n";
59
        echo sprintf("-> %s \n", $addText);
60
        sleep(180);
61
62
        $editInfo = new EditInfo(static::BOT_TALK_SUMMARY);
63
        $success = $page->addToBottomOfThePage($addText, $editInfo);
64
65
        return (bool)$success;
66
    }
67
68
    /**
69
     * @param string|null $toEditor
70
     * @param string|null $identation
71
     *
72
     * @return string
73
     * @throws Exception
74
     */
75
    private function generateTalkText(?string $toEditor = null, ?string $identation = ':')
76
    {
77
        if ($toEditor === 'Flow talk page manager') {
78
            $toEditor = null;
79
        }
80
        $to = ($toEditor) ? sprintf('@[[User:%s|%s]] : ', $toEditor, $toEditor) : ''; // {{notif}}
81
        $sentence = TextUtil::mb_ucfirst($this->getRandomSentence());
1 ignored issue
show
Bug introduced by
It seems like $this->getRandomSentence() can also be of type null; however, parameter $str of App\Domain\Utils\TextUtil::mb_ucfirst() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

81
        $sentence = TextUtil::mb_ucfirst(/** @scrutinizer ignore-type */ $this->getRandomSentence());
Loading history...
82
        if (!$sentence) {
83
            throw new Exception('no sentence');
84
        }
85
86
        return sprintf('%s%s%s --~~~~', $identation, $to, $sentence);
87
    }
88
89
    /**
90
     * Stupid ":::" talk page indentation prediction.
91
     *
92
     * @param string $text
93
     * @param string $author
94
     *
95
     * @return string ":::"
96
     */
97
    private function predictTalkIndentation(string $text, ?string $author = null): string
98
    {
99
        // extract last line
100
        $lines = explode("\n", trim($text));
101
        $lastLine = $lines[count($lines) - 1];
102
        if (preg_match('#^(:*).+#', $lastLine, $matches)) {
103
            if (!empty($matches[1])) {
104
                $nextIdent = $matches[1].':';
105
                if (empty($author)) {
106
                    return $nextIdent;
107
                }
108
                // search author signature link to check that he wrote on the page bottom
109
                if (preg_match(
110
                    '#\[\[(?:User|Utilisateur|Utilisatrice)\:'.preg_quote($author).'[|\]]#i',
111
                    $matches[0]
112
                )
113
                ) {
114
                    return $nextIdent;
115
                }
116
            }
117
        }
118
119
        return ':';
120
    }
121
122
    private function getRandomSentence(): ?string
123
    {
124
        $sentences = file(self::BOT_TALK_FILE);
125
        if (!$sentences) {
126
            return null;
127
        }
128
129
        return (string)trim($sentences[array_rand($sentences)]);
130
    }
131
132
    /**
133
     * Todo
134
     * https://www.mediawiki.org/wiki/API:Usercontribs.
135
     */
136
    public function botContribs(): string
137
    {
138
        $url
139
            = 'https://fr.wikipedia.org/w/api.php?action=query&list=usercontribs&ucuser='.getenv('BOT_NAME')
140
            .'&ucnamespace=0&uclimit=40&ucprop=title|timestamp|comment&format=json';
141
142
        return file_get_contents($url);
143
    }
144
}
145