NodeinfoPlugin.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Plugin that presents basic instance information using the [NodeInfo standard](http://nodeinfo.diaspora.software/).
  18. *
  19. * @package NodeInfo
  20. * @author Stéphane Bérubé <chimo@chromic.org>
  21. * @author Diogo Cordeiro <diogo@fc.up.pt>
  22. * @copyright 2018-2019 Free Software Foundation, Inc http://www.fsf.org
  23. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  24. */
  25. defined('GNUSOCIAL') || die();
  26. /**
  27. * Controls cache and routes
  28. *
  29. * @copyright 2018-2019 Free Software Foundation, Inc http://www.fsf.org
  30. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  31. */
  32. class NodeinfoPlugin extends Plugin
  33. {
  34. const PLUGIN_VERSION = '2.0.0';
  35. public function onRouterInitialized($m): bool
  36. {
  37. $m->connect(
  38. '.well-known/nodeinfo',
  39. ['action' => 'nodeinfojrd']
  40. );
  41. $m->connect(
  42. 'api/nodeinfo/2.0.json',
  43. ['action' => 'nodeinfo_2_0']
  44. );
  45. return true;
  46. }
  47. /**
  48. * Make sure necessary tables are filled out.
  49. *
  50. * @return bool hook true
  51. * @author Diogo Cordeiro <diogo@fc.up.pt>
  52. */
  53. public function onCheckSchema(): bool
  54. {
  55. // Ensure schema
  56. $schema = Schema::get();
  57. $schema->ensureTable('usage_stats', Usage_stats::schemaDef());
  58. // Ensure default rows
  59. if (Usage_stats::getKV('type', 'users') == null) {
  60. $us = new Usage_stats();
  61. $us->type = 'users';
  62. $us->insert();
  63. }
  64. if (Usage_stats::getKV('type', 'posts') == null) {
  65. $us = new Usage_stats();
  66. $us->type = 'posts';
  67. $us->insert();
  68. }
  69. if (Usage_stats::getKV('type', 'comments') == null) {
  70. $us = new Usage_stats();
  71. $us->type = 'comments';
  72. $us->insert();
  73. }
  74. return true;
  75. }
  76. /**
  77. * Increment notices/replies counter
  78. *
  79. * @param Notice $notice
  80. * @return bool hook flag
  81. * @author Diogo Cordeiro <diogo@fc.up.pt>
  82. */
  83. public function onStartNoticeDistribute(Notice $notice): bool
  84. {
  85. assert($notice->id > 0); // Ignore if not a valid notice
  86. $profile = $notice->getProfile();
  87. if (!$profile->isLocal()) {
  88. return true;
  89. }
  90. // Ignore for activity/non-(post/share)-verb notices
  91. if (method_exists('ActivityUtils', 'compareVerbs')) {
  92. $is_valid_verb = ActivityUtils::compareVerbs(
  93. $notice->verb,
  94. [ActivityVerb::POST,
  95. ActivityVerb::SHARE]
  96. );
  97. } else {
  98. $is_valid_verb = ($notice->verb == ActivityVerb::POST ||
  99. $notice->verb == ActivityVerb::SHARE);
  100. }
  101. if ($notice->source == 'activity' || !$is_valid_verb) {
  102. return true;
  103. }
  104. // Is a reply?
  105. if ($notice->reply_to) {
  106. $us = Usage_stats::getKV('type', 'comments');
  107. $us->count += 1;
  108. $us->update();
  109. return true;
  110. }
  111. // Is an Announce?
  112. if ($notice->isRepeat()) {
  113. return true;
  114. }
  115. $us = Usage_stats::getKV('type', 'posts');
  116. $us->count += 1;
  117. $us->update();
  118. // That was it
  119. return true;
  120. }
  121. /**
  122. * Decrement notices/replies counter
  123. *
  124. * @param User $user
  125. * @param Notice $notice
  126. * @return bool hook flag
  127. * @throws UserNoProfileException
  128. * @author Diogo Cordeiro <diogo@fc.up.pt>
  129. */
  130. public function onStartDeleteOwnNotice(User $user, Notice $notice): bool
  131. {
  132. $profile = $user->getProfile();
  133. // Only count local notices
  134. if (!$profile->isLocal()) {
  135. return true;
  136. }
  137. if ($notice->reply_to) {
  138. $us = Usage_stats::getKV('type', 'comments');
  139. $us->count -= 1;
  140. $us->update();
  141. return true;
  142. }
  143. $us = Usage_stats::getKV('type', 'posts');
  144. $us->count -= 1;
  145. $us->update();
  146. return true;
  147. }
  148. /**
  149. * Increment users counter
  150. *
  151. * @return bool hook flag
  152. * @author Diogo Cordeiro <diogo@fc.up.pt>
  153. */
  154. public function onEndRegistrationTry(): bool
  155. {
  156. $us = Usage_stats::getKV('type', 'users');
  157. $us->count += 1;
  158. $us->update();
  159. return true;
  160. }
  161. /**
  162. * Decrement users counter
  163. *
  164. * @return bool hook flag
  165. * @author Diogo Cordeiro <diogo@fc.up.pt>
  166. */
  167. public function onEndDeleteUser(): bool
  168. {
  169. $us = Usage_stats::getKV('type', 'users');
  170. $us->count -= 1;
  171. $us->update();
  172. return true;
  173. }
  174. /**
  175. * Plugin version information
  176. *
  177. * @param array $versions
  178. * @return bool hook true
  179. * @throws Exception
  180. */
  181. public function onPluginVersion(array &$versions): bool
  182. {
  183. $versions[] = [
  184. 'name' => 'Nodeinfo',
  185. 'version' => self::PLUGIN_VERSION,
  186. 'author' => 'Stéphane Bérubé, Diogo Cordeiro',
  187. 'homepage' => 'https://code.chromic.org/chimo/gs-nodeinfo',
  188. 'description' => _m('Plugin that presents basic instance information using the NodeInfo standard.')
  189. ];
  190. return true;
  191. }
  192. /**
  193. * Cache was added in a newer version of the plugin, this ensures we fix cached values on upgrade
  194. *
  195. * @return bool hook flag
  196. * @author Diogo Cordeiro <diogo@fc.up.pt>
  197. */
  198. public function onEndUpgrade(): bool
  199. {
  200. $users = new Usage_stats();
  201. if ($users->getUserCount() == 0) {
  202. define('NODEINFO_UPGRADE', true);
  203. require_once __DIR__ . DIRECTORY_SEPARATOR . 'scripts' . DIRECTORY_SEPARATOR . 'fix_stats.php';
  204. }
  205. return true;
  206. }
  207. }